From d166e1b83678aeaad6c2157aecf93163512fbd58 Mon Sep 17 00:00:00 2001 From: John Angel Date: Tue, 15 Oct 2024 16:07:11 +0200 Subject: [PATCH 1/2] fix: Cache watchers behavior --- src/hooks/useApollo.tsx | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/hooks/useApollo.tsx b/src/hooks/useApollo.tsx index 4ca91f4d9..cd08ba7b9 100644 --- a/src/hooks/useApollo.tsx +++ b/src/hooks/useApollo.tsx @@ -43,10 +43,11 @@ const LOGIN_WITH_DEVICE_TOKEN_MUTATION = gql(` } `); +type Watcher = () => void; + interface FullResult { data: any; variables: string; - watchers: (() => void)[]; } // The Apollo InMemory cache is way too complex for our purpose @@ -59,6 +60,7 @@ class FullResultCache extends ApolloCache { // ----------- Cache ----------------- private cache: Map = new Map(); + private watchers = new Map(); /* Extracts the name of a Query - query { ... } * This should be unique anyways as it is also used to generate typescript types @@ -91,7 +93,9 @@ class FullResultCache extends ApolloCache { if (!name) return undefined; const entry = this.cache.get(name); - if (entry && JSON.stringify(query.variables) === entry.variables) { + if (!entry) return undefined; + + if (JSON.stringify(query.variables) === entry.variables) { log('GraphQL Cache', `Read ${name} from cache`, entry); return entry; } else { @@ -107,20 +111,18 @@ class FullResultCache extends ApolloCache { const name = this.getQueryName(query); if (!name) return; - const existingEntry = this.getEntry(result); + const existingEntry = this.getEntry(query); if (!existingEntry) { this.cache.set(name, { data: result, - watchers: [], - variables: JSON.stringify(query.variables), + variables: JSON.stringify(query.variables ?? {}), }); log('GraphQL Cache', `Write ${name} to new Cache Entry`, result); } else { existingEntry.data = result; - existingEntry.watchers.forEach((it) => it()); - log('GraphQL Cache', `Write ${name} to existing Cache Entry`, result); } + this.watchers.get(name)?.forEach((watcher) => watcher()); } // ----------- ApolloCache Interface -------------- @@ -149,19 +151,24 @@ class FullResultCache extends ApolloCache { watch(watch: Cache.WatchOptions): () => void { const entry = this.getEntry(watch); + const name = this.getQueryName(watch); const watcher = () => { log('GraphQL Cache', 'fire watcher'); watch.callback(this.diff(watch)); }; - if (entry) { + if (name) { + log('GraphQL Cache', 'store watcher'); + this.watchers.set(name, this.watchers.get(name)?.concat(watcher) ?? []); + } + + if (entry && name) { log('GraphQL Cache', 'immediately fire watcher'); watch.callback(this.diff(watch)); - - entry.watchers.push(watcher); return () => { - entry.watchers = entry.watchers.filter((it) => it !== watcher); + const updatedWatchers = this.watchers.get(name)?.filter((it) => it !== watcher) ?? []; + this.watchers.set(name, updatedWatchers); log('GraphQL Cache', 'detach watcher'); }; } From 26f01ab49531733eea82bb0565142fa57862bd28 Mon Sep 17 00:00:00 2001 From: John Angel Date: Wed, 16 Oct 2024 09:30:28 +0200 Subject: [PATCH 2/2] fix: Run cleanup function if name is available --- src/hooks/useApollo.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hooks/useApollo.tsx b/src/hooks/useApollo.tsx index cd08ba7b9..a19f26e23 100644 --- a/src/hooks/useApollo.tsx +++ b/src/hooks/useApollo.tsx @@ -158,14 +158,14 @@ class FullResultCache extends ApolloCache { watch.callback(this.diff(watch)); }; + if (entry) { + log('GraphQL Cache', 'immediately fire watcher'); + watch.callback(this.diff(watch)); + } + if (name) { log('GraphQL Cache', 'store watcher'); this.watchers.set(name, this.watchers.get(name)?.concat(watcher) ?? []); - } - - if (entry && name) { - log('GraphQL Cache', 'immediately fire watcher'); - watch.callback(this.diff(watch)); return () => { const updatedWatchers = this.watchers.get(name)?.filter((it) => it !== watcher) ?? []; this.watchers.set(name, updatedWatchers);