fix: latest event query

This commit is contained in:
Shusui MOYATANI
2024-01-03 14:50:44 +09:00
parent 5a69036cd7
commit 541d036824

View File

@@ -6,6 +6,16 @@ import { compareEvents, pickLatestEvent, sortEvents } from '@/nostr/event/compar
import { BatchedEventsTask, registerTask } from '@/nostr/useBatchedEvents'; import { BatchedEventsTask, registerTask } from '@/nostr/useBatchedEvents';
import timeout from '@/utils/timeout'; 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 = export const latestEventQuery =
<K extends QueryKey>({ <K extends QueryKey>({
taskProvider, taskProvider,
@@ -17,22 +27,32 @@ export const latestEventQuery =
({ queryKey, signal }: { queryKey: K; signal?: AbortSignal }): Promise<NostrEvent | null> => { ({ queryKey, signal }: { queryKey: K; signal?: AbortSignal }): Promise<NostrEvent | null> => {
const task = taskProvider(queryKey); const task = taskProvider(queryKey);
if (task == null) return Promise.resolve(null); if (task == null) return Promise.resolve(null);
const promise = task.firstEventPromise().catch(() => { const promise = task
throw new Error(`event not found: ${JSON.stringify(queryKey)}`); .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) => { task.onUpdate((events) => {
const latest = pickLatestEvent(events); const latest = pickLatestEvent(events);
queryClient.setQueriesData<NostrEvent>({ queryKey }, (prev) => { queryClient.setQueriesData<NostrEvent>({ queryKey }, (prev) =>
if (latest != null && (prev == null || compareEvents(latest, prev) >= 0)) { chooseLatestEvent(prev, latest),
return latest; );
}
return undefined;
});
}); });
registerTask({ task, signal }); registerTask({ task, signal });
return timeout(15000, `${JSON.stringify(queryKey)}`)(promise); 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 = export const eventsQuery =
<K extends QueryKey>({ <K extends QueryKey>({
taskProvider, taskProvider,
@@ -44,14 +64,16 @@ export const eventsQuery =
({ queryKey, signal }: { queryKey: K; signal?: AbortSignal }): Promise<NostrEvent[]> => { ({ queryKey, signal }: { queryKey: K; signal?: AbortSignal }): Promise<NostrEvent[]> => {
const task = taskProvider(queryKey); const task = taskProvider(queryKey);
if (task == null) return Promise.resolve([]); 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) => { task.onUpdate((events) => {
// TODO consider kind:5 deletion // TODO consider kind:5 deletion
queryClient.setQueriesData<NostrEvent[]>({ queryKey }, (prev) => { queryClient.setQueriesData<NostrEvent[]>({ queryKey }, (prev) => mergeEvents(prev, events));
if (prev == null) return events;
const deduped = uniqBy([...prev, ...events], (e) => e.id);
return sortEvents(deduped);
});
}); });
registerTask({ task, signal }); registerTask({ task, signal });
return timeout(15000, `${JSON.stringify(queryKey)}`)(promise); return timeout(15000, `${JSON.stringify(queryKey)}`)(promise);