Skip to content

Commit

Permalink
Call cache.init() in cache.restore to reset EntityStore and result ca…
Browse files Browse the repository at this point in the history
…che.

If the cache already has much data in it, the speedup from throwing it
all away before replacing it (and thus not having to delete each entity
one by one) could be pretty significant.
  • Loading branch information
benjamn committed Jun 23, 2021
1 parent f7d7413 commit 7b11bd7
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
11 changes: 11 additions & 0 deletions src/cache/inmemory/__tests__/__snapshots__/cache.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Cache cache.restore replaces cache.{store{Reader,Writer},maybeBroadcastWatch} 1`] = `
Object {
"ROOT_QUERY": Object {
"__typename": "Query",
"a": "ay",
"b": "bee",
"c": "see",
},
}
`;

exports[`Cache writeFragment will write some deeply nested data into the store at any id (1/2) 1`] = `
Object {
"__META": Object {
Expand Down
55 changes: 54 additions & 1 deletion src/cache/inmemory/__tests__/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { InMemoryCache, InMemoryCacheConfig } from '../inMemoryCache';

jest.mock('optimism');
import { wrap } from 'optimism';
import { StoreReader } from '../readFromStore';
import { StoreWriter } from '../writeToStore';
import { ObjectCanon } from '../object-canon';

disableFragmentWarnings();

Expand Down Expand Up @@ -1330,7 +1333,57 @@ describe('Cache', () => {
);
});

describe('batch', () => {
describe('cache.restore', () => {
it('replaces cache.{store{Reader,Writer},maybeBroadcastWatch}', () => {
const cache = new InMemoryCache;
const query = gql`query { a b c }`;

const originalReader = cache["storeReader"];
expect(originalReader).toBeInstanceOf(StoreReader);

const originalWriter = cache["storeWriter"];
expect(originalWriter).toBeInstanceOf(StoreWriter);

const originalMBW = cache["maybeBroadcastWatch"];
expect(typeof originalMBW).toBe("function");

const originalCanon = originalReader["canon"];
expect(originalCanon).toBeInstanceOf(ObjectCanon);

cache.writeQuery({
query,
data: {
a: "ay",
b: "bee",
c: "see",
},
});

const snapshot = cache.extract();
expect(snapshot).toMatchSnapshot();

cache.restore({});
expect(cache.extract()).toEqual({});
expect(cache.readQuery({ query })).toBe(null);

cache.restore(snapshot);
expect(cache.extract()).toEqual(snapshot);
expect(cache.readQuery({ query })).toEqual({
a: "ay",
b: "bee",
c: "see",
});

expect(originalReader).not.toBe(cache["storeReader"]);
expect(originalWriter).not.toBe(cache["storeWriter"]);
expect(originalMBW).not.toBe(cache["maybeBroadcastWatch"]);
// The cache.storeReader.canon is preserved by default, but can be dropped
// by passing preserveCanon:false to cache.gc.
expect(originalCanon).toBe(cache["storeReader"]["canon"]);
});
});

describe('cache.batch', () => {
const last = <E>(array: E[]) => array[array.length - 1];

function watch(cache: InMemoryCache, query: DocumentNode) {
Expand Down
4 changes: 4 additions & 0 deletions src/cache/inmemory/inMemoryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
}

public restore(data: NormalizedCacheObject): this {
this.init();
// Since calling this.init() discards/replaces the entire StoreReader, along
// with the result caches it maintains, this.data.replace(data) won't have
// to bother deleting the old data.
if (data) this.data.replace(data);
return this;
}
Expand Down

0 comments on commit 7b11bd7

Please sign in to comment.