import { Debug, type Event, type Filter, LRUCache } from '@/deps.ts'; import { getFilterId, getMicroFilters, isMicrofilter } from '@/filter.ts'; import { type EventStore, type GetEventsOpts } from '@/store.ts'; /** In-memory data store for events using microfilters. */ class Memorelay implements EventStore { #debug = Debug('ditto:memorelay'); #events: LRUCache; constructor(...args: ConstructorParameters>) { this.#events = new LRUCache(...args); } /** Get events from memory. */ getEvents(filters: Filter[], opts: GetEventsOpts = {}): Promise[]> { if (opts.signal?.aborted) return Promise.resolve([]); if (!filters.length) return Promise.resolve([]); this.#debug('REQ', JSON.stringify(filters)); const results: Event[] = []; for (const filter of filters) { if (isMicrofilter(filter)) { const event = this.#events.get(getFilterId(filter)); if (event) { results.push(event as Event); } } } return Promise.resolve(results); } /** Insert an event into memory. */ storeEvent(event: Event): Promise { for (const microfilter of getMicroFilters(event)) { const filterId = getFilterId(microfilter); const existing = this.#events.get(filterId); if (!existing || event.created_at > existing.created_at) { this.#events.set(filterId, event); } } return Promise.resolve(); } /** Count events in memory for the filters. */ async countEvents(filters: Filter[]): Promise { const events = await this.getEvents(filters); return events.length; } /** Delete events from memory. */ deleteEvents(filters: Filter[]): Promise { for (const filter of filters) { if (isMicrofilter(filter)) { this.#events.delete(getFilterId(filter)); } } return Promise.resolve(); } } export { Memorelay };