From 541d036824aaf830f7df3fb6e4c4fd57abf3917d Mon Sep 17 00:00:00 2001 From: Shusui MOYATANI Date: Wed, 3 Jan 2024 14:50:44 +0900 Subject: [PATCH] fix: latest event query --- src/nostr/query.ts | 52 +++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/src/nostr/query.ts b/src/nostr/query.ts index 0dfc72b..c4a04e7 100644 --- a/src/nostr/query.ts +++ b/src/nostr/query.ts @@ -6,6 +6,16 @@ import { compareEvents, pickLatestEvent, sortEvents } from '@/nostr/event/compar import { BatchedEventsTask, registerTask } from '@/nostr/useBatchedEvents'; import timeout from '@/utils/timeout'; +const chooseLatestEvent = ( + prev: NostrEvent | undefined, + latest: NostrEvent | undefined, +): NostrEvent | undefined => { + if (latest != null && (prev == null || compareEvents(latest, prev) >= 0)) { + return latest; + } + return prev; +}; + export const latestEventQuery = ({ taskProvider, @@ -17,22 +27,32 @@ export const latestEventQuery = ({ queryKey, signal }: { queryKey: K; signal?: AbortSignal }): Promise => { const task = taskProvider(queryKey); if (task == null) return Promise.resolve(null); - const promise = task.firstEventPromise().catch(() => { - throw new Error(`event not found: ${JSON.stringify(queryKey)}`); - }); + const promise = task + .firstEventPromise() + .then((latest) => { + const prev = queryClient.getQueryData(queryKey) as NostrEvent; + return chooseLatestEvent(prev, latest) ?? null; + }) + .catch(() => { + throw new Error(`event not found: ${JSON.stringify(queryKey)}`); + }); + task.onUpdate((events) => { const latest = pickLatestEvent(events); - queryClient.setQueriesData({ queryKey }, (prev) => { - if (latest != null && (prev == null || compareEvents(latest, prev) >= 0)) { - return latest; - } - return undefined; - }); + queryClient.setQueriesData({ queryKey }, (prev) => + chooseLatestEvent(prev, latest), + ); }); registerTask({ task, signal }); return timeout(15000, `${JSON.stringify(queryKey)}`)(promise); }; +const mergeEvents = (prev: NostrEvent[] | undefined, events: NostrEvent[]) => { + if (prev == null) return events; + const deduped = uniqBy([...prev, ...events], (e) => e.id); + return sortEvents(deduped); +}; + export const eventsQuery = ({ taskProvider, @@ -44,14 +64,16 @@ export const eventsQuery = ({ queryKey, signal }: { queryKey: K; signal?: AbortSignal }): Promise => { const task = taskProvider(queryKey); if (task == null) return Promise.resolve([]); - const promise = task.toUpdatePromise().catch(() => []); + const promise = task + .toUpdatePromise() + .then((events) => { + const prev: NostrEvent[] = queryClient.getQueryData(queryKey) ?? []; + return mergeEvents(prev, events); + }) + .catch(() => []); task.onUpdate((events) => { // TODO consider kind:5 deletion - queryClient.setQueriesData({ queryKey }, (prev) => { - if (prev == null) return events; - const deduped = uniqBy([...prev, ...events], (e) => e.id); - return sortEvents(deduped); - }); + queryClient.setQueriesData({ queryKey }, (prev) => mergeEvents(prev, events)); }); registerTask({ task, signal }); return timeout(15000, `${JSON.stringify(queryKey)}`)(promise);