Skip to content

Commit

Permalink
Require cache.reset({ discardWatches: true }) to clear cache.watches.
Browse files Browse the repository at this point in the history
As reported in issue #8851, PR #8826 was a breaking change for code
expecting cache.watches to be restarted after cache.reset() is called.

This commit establishes a small but extensible Cache.ResetOptions API
for the cache.reset method, which allows the handling of watches to be
configured via options.discardWatches, which defaults to false, thus
restoring the behavior of cache.reset() from before #8826.

If you need the behavior introduced by #8826, you can now opt (back)
into that behavior by calling cache.reset({ discardWatches: true }).
  • Loading branch information
benjamn committed Sep 27, 2021
1 parent ffaf81d commit 6e1e046
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 10 deletions.
5 changes: 4 additions & 1 deletion src/cache/core/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ export abstract class ApolloCache<TSerialized> implements DataProxy {
): Reference | undefined;
public abstract diff<T>(query: Cache.DiffOptions): Cache.DiffResult<T>;
public abstract watch(watch: Cache.WatchOptions): () => void;
public abstract reset(): Promise<void>;

// Empty the cache and restart all current watches (unless
// options.discardWatches is true).
public abstract reset(options?: Cache.ResetOptions): Promise<void>;

// Remove whole objects from the cache by passing just options.id, or
// specific fields by passing options.field and/or options.args. If no
Expand Down
6 changes: 6 additions & 0 deletions src/cache/core/types/Cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ export namespace Cache {
broadcast?: boolean;
}

// Although you can call cache.reset() without options, its behavior can be
// configured by passing a Cache.ResetOptions object.
export interface ResetOptions {
discardWatches?: boolean;
}

export interface ModifyOptions {
id?: string;
fields: Modifiers | Modifier<any>;
Expand Down
4 changes: 2 additions & 2 deletions src/cache/inmemory/__tests__/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3239,7 +3239,7 @@ describe("ReactiveVar and makeVar", () => {
d: 2,
});

cache.reset();
cache.reset({ discardWatches: true });
expect(cache["watches"].size).toBe(0);

expect(diffCounts).toEqual({
Expand Down Expand Up @@ -3290,7 +3290,7 @@ describe("ReactiveVar and makeVar", () => {
f: 2,
});

cache.reset();
cache.reset({ discardWatches: true });
expect(cache["watches"].size).toBe(0);

nameVar("Danielle");
Expand Down
24 changes: 17 additions & 7 deletions src/cache/inmemory/inMemoryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,17 +343,27 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
}
}

public reset(): Promise<void> {
public reset(options?: Cache.ResetOptions): Promise<void> {
this.init();

// Similar to what happens in the unsubscribe function returned by
// cache.watch, applied to all current watches.
this.watches.forEach(watch => this.maybeBroadcastWatch.forget(watch));
this.watches.clear();
forgetCache(this);

canonicalStringify.reset();

if (options && options.discardWatches) {
// Similar to what happens in the unsubscribe function returned by
// cache.watch, applied to all current watches.
this.watches.forEach(watch => this.maybeBroadcastWatch.forget(watch));
this.watches.clear();
forgetCache(this);
} else {
// Calling this.init() above unblocks all maybeBroadcastWatch caching, so
// this.broadcastWatches() triggers a broadcast to every current watcher
// (letting them know their data is now missing). This default behavior is
// convenient because it means the watches do not have to be manually
// reestablished after resetting the cache. To prevent this broadcast and
// cancel all watches, pass true for options.discardWatches.
this.broadcastWatches();
}

return Promise.resolve();
}

Expand Down

0 comments on commit 6e1e046

Please sign in to comment.