Add a function to calculate the intrinsic limit of a filter
This commit is contained in:
parent
80e6147927
commit
5bffffe07b
|
@ -4,7 +4,7 @@ import { assertEquals } from '@/deps-test.ts';
|
|||
import event0 from '~/fixtures/events/event-0.json' assert { type: 'json' };
|
||||
import event1 from '~/fixtures/events/event-1.json' assert { type: 'json' };
|
||||
|
||||
import { eventToMicroFilter, getFilterId, getMicroFilters, isMicrofilter } from './filter.ts';
|
||||
import { eventToMicroFilter, getFilterId, getFilterLimit, getMicroFilters, isMicrofilter } from './filter.ts';
|
||||
|
||||
Deno.test('getMicroFilters', () => {
|
||||
const event = event0 as Event<0>;
|
||||
|
@ -35,3 +35,13 @@ Deno.test('getFilterId', () => {
|
|||
'{"authors":["79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6"],"kinds":[0]}',
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test('getFilterLimit', () => {
|
||||
assertEquals(getFilterLimit({ ids: [event0.id] }), 1);
|
||||
assertEquals(getFilterLimit({ ids: [event0.id], limit: 2 }), 1);
|
||||
assertEquals(getFilterLimit({ ids: [event0.id], limit: 0 }), 0);
|
||||
assertEquals(getFilterLimit({ ids: [event0.id], limit: -1 }), 0);
|
||||
assertEquals(getFilterLimit({ kinds: [0], authors: [event0.pubkey] }), 1);
|
||||
assertEquals(getFilterLimit({ kinds: [1], authors: [event0.pubkey] }), Infinity);
|
||||
assertEquals(getFilterLimit({}), Infinity);
|
||||
});
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Conf } from '@/config.ts';
|
|||
import { type Event, type Filter, matchFilters, stringifyStable, z } from '@/deps.ts';
|
||||
import { nostrIdSchema } from '@/schemas/nostr.ts';
|
||||
import { type EventData } from '@/types.ts';
|
||||
import { isReplaceableKind } from '@/kinds.ts';
|
||||
|
||||
/** Additional properties that may be added by Ditto to events. */
|
||||
type Relation = 'author' | 'author_stats' | 'event_stats';
|
||||
|
@ -82,11 +83,34 @@ function isMicrofilter(filter: Filter): filter is MicroFilter {
|
|||
return microFilterSchema.safeParse(filter).success;
|
||||
}
|
||||
|
||||
/** Calculate the intrinsic limit of a filter. */
|
||||
function getFilterLimit(filter: Filter): number {
|
||||
if (filter.ids && !filter.ids.length) return 0;
|
||||
if (filter.kinds && !filter.kinds.length) return 0;
|
||||
if (filter.authors && !filter.authors.length) return 0;
|
||||
|
||||
return Math.min(
|
||||
Math.max(0, filter.limit ?? Infinity),
|
||||
filter.ids?.length ?? Infinity,
|
||||
filter.authors?.length &&
|
||||
filter.kinds?.every((kind) => isReplaceableKind(kind))
|
||||
? filter.authors.length * filter.kinds.length
|
||||
: Infinity,
|
||||
);
|
||||
}
|
||||
|
||||
/** Returns true if the filter could potentially return any stored events at all. */
|
||||
function canFilter(filter: Filter): boolean {
|
||||
return getFilterLimit(filter) > 0;
|
||||
}
|
||||
|
||||
export {
|
||||
type AuthorMicrofilter,
|
||||
canFilter,
|
||||
type DittoFilter,
|
||||
eventToMicroFilter,
|
||||
getFilterId,
|
||||
getFilterLimit,
|
||||
getMicroFilters,
|
||||
type IdMicrofilter,
|
||||
isMicrofilter,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Debug, type Event, type Filter, LRUCache, matchFilter, matchFilters } from '@/deps.ts';
|
||||
import { canFilter, getFilterLimit } from '@/filter.ts';
|
||||
import { type EventStore, type GetEventsOpts } from '@/store.ts';
|
||||
|
||||
/** In-memory data store for events. */
|
||||
|
@ -27,6 +28,7 @@ class Memorelay implements EventStore {
|
|||
/** Get events from memory. */
|
||||
getEvents<K extends number>(filters: Filter<K>[], opts: GetEventsOpts = {}): Promise<Event<K>[]> {
|
||||
if (opts.signal?.aborted) return Promise.resolve([]);
|
||||
filters = filters.filter(canFilter);
|
||||
if (!filters.length) return Promise.resolve([]);
|
||||
this.#debug('REQ', JSON.stringify(filters));
|
||||
|
||||
|
@ -37,7 +39,7 @@ class Memorelay implements EventStore {
|
|||
let index = 0;
|
||||
|
||||
for (const filter of filters) {
|
||||
const limit = filter.limit ?? Infinity;
|
||||
const limit = getFilterLimit(filter);
|
||||
const usage = usages[index] ?? 0;
|
||||
|
||||
if (usage >= limit) {
|
||||
|
@ -50,7 +52,7 @@ class Memorelay implements EventStore {
|
|||
index++;
|
||||
}
|
||||
|
||||
if (filters.every((filter, index) => usages[index] >= (filter.limit ?? Infinity))) {
|
||||
if (filters.every((filter, index) => usages[index] >= getFilterLimit(filter))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue