Memorelay: do some premature optimizations
This commit is contained in:
parent
c235fa6123
commit
48ce1ba6c9
|
@ -1,4 +1,4 @@
|
||||||
import { Debug, type Event, type Filter, LRUCache, matchFilter, matchFilters } from '@/deps.ts';
|
import { Debug, type Event, type Filter, LRUCache, matchFilter } from '@/deps.ts';
|
||||||
import { normalizeFilters } from '@/filter.ts';
|
import { normalizeFilters } from '@/filter.ts';
|
||||||
import { type EventStore, type GetEventsOpts } from '@/store.ts';
|
import { type EventStore, type GetEventsOpts } from '@/store.ts';
|
||||||
|
|
||||||
|
@ -27,32 +27,62 @@ class Memorelay implements EventStore {
|
||||||
|
|
||||||
/** Get events from memory. */
|
/** Get events from memory. */
|
||||||
getEvents<K extends number>(filters: Filter<K>[], opts: GetEventsOpts = {}): Promise<Event<K>[]> {
|
getEvents<K extends number>(filters: Filter<K>[], opts: GetEventsOpts = {}): Promise<Event<K>[]> {
|
||||||
if (opts.signal?.aborted) return Promise.resolve([]);
|
|
||||||
filters = normalizeFilters(filters);
|
filters = normalizeFilters(filters);
|
||||||
|
|
||||||
|
if (opts.signal?.aborted) return Promise.resolve([]);
|
||||||
if (!filters.length) return Promise.resolve([]);
|
if (!filters.length) return Promise.resolve([]);
|
||||||
|
|
||||||
this.#debug('REQ', JSON.stringify(filters));
|
this.#debug('REQ', JSON.stringify(filters));
|
||||||
|
|
||||||
|
/** Event results to return. */
|
||||||
const results: Event<K>[] = [];
|
const results: Event<K>[] = [];
|
||||||
const usages: number[] = [];
|
|
||||||
|
|
||||||
|
/** Number of times an event has been added to results for each filter. */
|
||||||
|
const filterUsages: number[] = [];
|
||||||
|
|
||||||
|
/** Check if all filters have been satisfied. */
|
||||||
|
function checkSatisfied() {
|
||||||
|
return results.length >= (opts.limit ?? Infinity) ||
|
||||||
|
filters.every((filter, index) => filter.limit && (filterUsages[index] >= filter.limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize for filters with IDs.
|
||||||
|
filters.forEach((filter, index) => {
|
||||||
|
if (filter.ids) {
|
||||||
|
for (const id of filter.ids) {
|
||||||
|
const event = this.#cache.get(id);
|
||||||
|
if (event && matchFilter(filter, event)) {
|
||||||
|
results.push(event as Event<K>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filterUsages[index] = Infinity;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return early if all filters are satisfied.
|
||||||
|
if (checkSatisfied()) {
|
||||||
|
return Promise.resolve(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek through all events in memory.
|
||||||
for (const event of this.#events()) {
|
for (const event of this.#events()) {
|
||||||
let index = 0;
|
filters.forEach((filter, index) => {
|
||||||
|
|
||||||
for (const filter of filters) {
|
|
||||||
const limit = filter.limit ?? Infinity;
|
const limit = filter.limit ?? Infinity;
|
||||||
const usage = usages[index] ?? 0;
|
const usage = filterUsages[index] ?? 0;
|
||||||
|
|
||||||
if (usage >= limit) {
|
if (usage >= limit) {
|
||||||
continue;
|
return;
|
||||||
} else if (matchFilter(filter, event)) {
|
} else if (matchFilter(filter, event)) {
|
||||||
results.push(event as Event<K>);
|
results.push(event as Event<K>);
|
||||||
usages[index] = usage + 1;
|
this.#cache.get(event.id);
|
||||||
|
filterUsages[index] = usage + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
});
|
||||||
|
|
||||||
if (filters.every((filter, index) => filter.limit && (usages[index] >= filter.limit))) {
|
// Check after each event if we can return.
|
||||||
|
if (checkSatisfied()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,11 +103,9 @@ class Memorelay implements EventStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Delete events from memory. */
|
/** Delete events from memory. */
|
||||||
deleteEvents(filters: Filter[]): Promise<void> {
|
async deleteEvents(filters: Filter[]): Promise<void> {
|
||||||
for (const event of this.#events()) {
|
for (const event of await this.getEvents(filters)) {
|
||||||
if (matchFilters(filters, event)) {
|
this.#cache.delete(event.id);
|
||||||
this.#cache.delete(event.id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue