search: fix abort signals
This commit is contained in:
parent
412f71599a
commit
89af83c660
|
@ -30,9 +30,11 @@ const searchController: AppController = async (c) => {
|
|||
return c.json({ error: 'Bad request', schema: result.error }, 422);
|
||||
}
|
||||
|
||||
const signal = AbortSignal.timeout(1000);
|
||||
|
||||
const [event, events] = await Promise.all([
|
||||
lookupEvent(result.data),
|
||||
searchEvents(result.data),
|
||||
lookupEvent(result.data, signal),
|
||||
searchEvents(result.data, signal),
|
||||
]);
|
||||
|
||||
if (event) {
|
||||
|
@ -62,7 +64,7 @@ const searchController: AppController = async (c) => {
|
|||
};
|
||||
|
||||
/** Get events for the search params. */
|
||||
function searchEvents({ q, type, limit, account_id }: SearchQuery): Promise<Event[]> {
|
||||
function searchEvents({ q, type, limit, account_id }: SearchQuery, signal: AbortSignal): Promise<Event[]> {
|
||||
if (type === 'hashtags') return Promise.resolve([]);
|
||||
|
||||
const filter: DittoFilter = {
|
||||
|
@ -76,7 +78,7 @@ function searchEvents({ q, type, limit, account_id }: SearchQuery): Promise<Even
|
|||
filter.authors = [account_id];
|
||||
}
|
||||
|
||||
return searchStore.getEvents([filter]);
|
||||
return searchStore.getEvents([filter], { signal });
|
||||
}
|
||||
|
||||
/** Get event kinds to search from `type` query param. */
|
||||
|
@ -92,7 +94,7 @@ function typeToKinds(type: SearchQuery['type']): number[] {
|
|||
}
|
||||
|
||||
/** Resolve a searched value into an event, if applicable. */
|
||||
async function lookupEvent(query: SearchQuery, signal = AbortSignal.timeout(1000)): Promise<Event | undefined> {
|
||||
async function lookupEvent(query: SearchQuery, signal: AbortSignal): Promise<Event | undefined> {
|
||||
const filters = await getLookupFilters(query);
|
||||
const [event] = await searchStore.getEvents(filters, { limit: 1, signal });
|
||||
return event;
|
||||
|
|
|
@ -5,15 +5,16 @@ interface HydrateEventOpts<K extends number> {
|
|||
events: DittoEvent<K>[];
|
||||
filters: DittoFilter<K>[];
|
||||
storage: EventStore;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
/** Hydrate event relationships using the provided storage. */
|
||||
async function hydrateEvents<K extends number>(opts: HydrateEventOpts<K>): Promise<DittoEvent<K>[]> {
|
||||
const { events, filters, storage } = opts;
|
||||
const { events, filters, storage, signal } = opts;
|
||||
|
||||
if (filters.some((filter) => filter.relations?.includes('author'))) {
|
||||
const pubkeys = new Set([...events].map((event) => event.pubkey));
|
||||
const authors = await storage.getEvents([{ kinds: [0], authors: [...pubkeys] }]);
|
||||
const authors = await storage.getEvents([{ kinds: [0], authors: [...pubkeys] }], { signal });
|
||||
|
||||
for (const event of events) {
|
||||
event.author = authors.find((author) => author.pubkey === event.pubkey);
|
||||
|
|
|
@ -50,14 +50,23 @@ class SearchStore implements EventStore {
|
|||
this.#debug(`Searching for "${query}" at ${this.#relay.socket.url}...`);
|
||||
|
||||
const sub = this.#relay.req(filters, opts);
|
||||
sub.eoseSignal.onabort = () => sub.close();
|
||||
|
||||
const close = () => {
|
||||
sub.close();
|
||||
opts?.signal?.removeEventListener('abort', close);
|
||||
sub.eoseSignal.removeEventListener('abort', close);
|
||||
};
|
||||
|
||||
opts?.signal?.addEventListener('abort', close, { once: true });
|
||||
sub.eoseSignal.addEventListener('abort', close, { once: true });
|
||||
|
||||
const events = new EventSet<DittoEvent<K>>();
|
||||
|
||||
for await (const event of sub) {
|
||||
events.add(event);
|
||||
}
|
||||
|
||||
return hydrateEvents({ events: [...events], filters, storage: this.#hydrator });
|
||||
return hydrateEvents({ events: [...events], filters, storage: this.#hydrator, signal: opts?.signal });
|
||||
} else {
|
||||
this.#debug(`Searching for "${query}" locally...`);
|
||||
return this.#fallback.getEvents(filters, opts);
|
||||
|
|
Loading…
Reference in New Issue