Skip to content

Commit

Permalink
Support cache.gc({ resetResultCache: true }) to jettison result cache.
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamn committed Jun 23, 2021
1 parent 74648e3 commit 44a4955
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 5 deletions.
11 changes: 11 additions & 0 deletions src/cache/inmemory/__tests__/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2603,6 +2603,17 @@ describe("InMemoryCache#modify", () => {

expect(aResults).toEqual([a123, a124]);
expect(bResults).toEqual([b321, b322]);

// Check that resetting the result cache does not trigger additional watch
// notifications.
expect(cache.gc({
resetResultCache: true,
})).toEqual([]);
expect(aResults).toEqual([a123, a124]);
expect(bResults).toEqual([b321, b322]);
cache["broadcastWatches"]();
expect(aResults).toEqual([a123, a124]);
expect(bResults).toEqual([b321, b322]);
});

it("should handle argument-determined field identities", () => {
Expand Down
33 changes: 30 additions & 3 deletions src/cache/inmemory/__tests__/entityStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ApolloCache } from '../../core/cache';
import { Cache } from '../../core/types/Cache';
import { Reference, makeReference, isReference } from '../../../utilities/graphql/storeUtils';
import { MissingFieldError } from '../..';
import { TypedDocumentNode } from '@graphql-typed-document-node/core';

describe('EntityStore', () => {
it('should support result caching if so configured', () => {
Expand Down Expand Up @@ -56,7 +57,17 @@ describe('EntityStore', () => {
},
});

const query = gql`
const query: TypedDocumentNode<{
book: {
__typename: string;
title: string;
isbn: string;
author: {
__typename: string;
name: string;
};
};
}> = gql`
query {
book {
title
Expand Down Expand Up @@ -159,11 +170,16 @@ describe('EntityStore', () => {
},
});

const resultBeforeGC = cache.readQuery({ query });

expect(cache.gc().sort()).toEqual([
'Author:Ray Bradbury',
'Book:9781451673319',
]);

const resultAfterGC = cache.readQuery({ query });
expect(resultBeforeGC).toBe(resultAfterGC);

expect(cache.extract()).toEqual({
ROOT_QUERY: {
__typename: "Query",
Expand All @@ -184,8 +200,19 @@ describe('EntityStore', () => {
},
});

// Nothing left to garbage collect.
expect(cache.gc()).toEqual([]);
// Nothing left to garbage collect, but let's also reset the result cache to
// demonstrate that the recomputed cache results are unchanged.
expect(cache.gc({
resetResultCache: true,
})).toEqual([]);

const resultAfterFullGC = cache.readQuery({ query });
expect(resultAfterFullGC).toEqual(resultBeforeGC);
expect(resultAfterFullGC).toEqual(resultAfterGC);
// These !== relations are triggered by the resetResultCache:true option
// passed to cache.gc, above.
expect(resultAfterFullGC).not.toBe(resultBeforeGC);
expect(resultAfterFullGC).not.toBe(resultAfterGC);

// Go back to the pre-GC snapshot.
cache.restore(snapshot);
Expand Down
17 changes: 15 additions & 2 deletions src/cache/inmemory/inMemoryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
// original this.data cache object.
this.optimisticData = rootStore.stump;

this.resetResultCache();
}

private resetResultCache() {
// The StoreWriter is mostly stateless and so doesn't really need to be
// reset, but it does need to have its writer.storeReader reference updated,
// so it's simpler to update this.storeWriter as well.
this.storeWriter = new StoreWriter(
this,
this.storeReader = new StoreReader({
Expand Down Expand Up @@ -263,9 +270,15 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
}

// Request garbage collection of unreachable normalized entities.
public gc() {
public gc(options?: {
resetResultCache?: boolean;
}) {
canonicalStringify.reset();
return this.optimisticData.gc();
const ids = this.optimisticData.gc();
if (options && options.resetResultCache) {
this.resetResultCache();
}
return ids;
}

// Call this method to ensure the given root ID remains in the cache after
Expand Down

0 comments on commit 44a4955

Please sign in to comment.