Upgrade NSpec, update `count` interface
This commit is contained in:
parent
676bd04229
commit
cb80770fc7
|
@ -96,7 +96,7 @@ function connectStream(socket: WebSocket) {
|
|||
|
||||
/** Handle COUNT. Return the number of events matching the filters. */
|
||||
async function handleCount([_, subId, ...rest]: ClientCOUNT): Promise<void> {
|
||||
const count = await eventsDB.count(prepareFilters(rest));
|
||||
const { count } = await eventsDB.count(prepareFilters(rest));
|
||||
send(['COUNT', subId, { count, approximate: false }]);
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,6 @@ export { default as Debug } from 'https://gitlab.com/soapbox-pub/stickynotes/-/r
|
|||
export {
|
||||
LNURL,
|
||||
type LNURLDetails,
|
||||
type MapCache,
|
||||
NCache,
|
||||
NIP05,
|
||||
type NostrEvent,
|
||||
|
@ -93,6 +92,6 @@ export {
|
|||
NSet,
|
||||
type NStore,
|
||||
type NStoreOpts,
|
||||
} from 'https://gitlab.com/soapbox-pub/NSpec/-/raw/8ce84d9acd9925f51b51c00374eae81a5031559b/mod.ts';
|
||||
} from 'https://gitlab.com/soapbox-pub/NSpec/-/raw/v0.1.0/mod.ts';
|
||||
|
||||
export type * as TypeFest from 'npm:type-fest@^4.3.0';
|
||||
|
|
|
@ -46,7 +46,7 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise<void
|
|||
|
||||
/** Encounter the event, and return whether it has already been encountered. */
|
||||
async function encounterEvent(event: NostrEvent, signal: AbortSignal): Promise<boolean> {
|
||||
const preexisting = (await cache.count([{ ids: [event.id] }])) > 0;
|
||||
const preexisting = (await cache.count([{ ids: [event.id] }])).count > 0;
|
||||
cache.event(event);
|
||||
reqmeister.event(event, { signal });
|
||||
return preexisting;
|
||||
|
@ -72,10 +72,10 @@ async function storeEvent(event: DittoEvent, opts: StoreEventOpts): Promise<void
|
|||
const { force = false, signal } = opts;
|
||||
|
||||
if (force || event.user || isAdminEvent(event) || await isLocallyFollowed(event.pubkey)) {
|
||||
const isDeleted = await eventsDB.count(
|
||||
const isDeleted = (await eventsDB.count(
|
||||
[{ kinds: [5], authors: [Conf.pubkey, event.pubkey], '#e': [event.id], limit: 1 }],
|
||||
opts,
|
||||
) > 0;
|
||||
)).count > 0;
|
||||
|
||||
if (isDeleted) {
|
||||
return Promise.reject(new RelayError('blocked', 'event was deleted'));
|
||||
|
@ -145,13 +145,17 @@ function trackRelays(event: NostrEvent) {
|
|||
}
|
||||
|
||||
/** Queue related events to fetch. */
|
||||
function fetchRelatedEvents(event: DittoEvent, signal: AbortSignal) {
|
||||
async function fetchRelatedEvents(event: DittoEvent, signal: AbortSignal) {
|
||||
if (!event.user) {
|
||||
reqmeister.req({ kinds: [0], authors: [event.pubkey] }, { signal }).catch(() => {});
|
||||
}
|
||||
|
||||
for (const [name, id, relay] of event.tags) {
|
||||
if (name === 'e' && !cache.count([{ ids: [id] }])) {
|
||||
reqmeister.req({ ids: [id] }, { relays: [relay] }).catch(() => {});
|
||||
if (name === 'e') {
|
||||
const { count } = await cache.count([{ ids: [id] }]);
|
||||
if (!count) {
|
||||
reqmeister.req({ ids: [id] }, { relays: [relay] }).catch(() => {});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ import { EventsDB } from './events-db.ts';
|
|||
const eventsDB = new EventsDB(db);
|
||||
|
||||
Deno.test('count filters', async () => {
|
||||
assertEquals(await eventsDB.count([{ kinds: [1] }]), 0);
|
||||
assertEquals((await eventsDB.count([{ kinds: [1] }])).count, 0);
|
||||
await eventsDB.event(event1);
|
||||
assertEquals(await eventsDB.count([{ kinds: [1] }]), 1);
|
||||
assertEquals((await eventsDB.count([{ kinds: [1] }])).count, 1);
|
||||
});
|
||||
|
||||
Deno.test('insert and filter events', async () => {
|
||||
|
@ -55,11 +55,11 @@ Deno.test('query events with local filter', async () => {
|
|||
});
|
||||
|
||||
Deno.test('inserting replaceable events', async () => {
|
||||
assertEquals(await eventsDB.count([{ kinds: [0], authors: [event0.pubkey] }]), 0);
|
||||
assertEquals((await eventsDB.count([{ kinds: [0], authors: [event0.pubkey] }])).count, 0);
|
||||
|
||||
await eventsDB.event(event0);
|
||||
await assertRejects(() => eventsDB.event(event0));
|
||||
assertEquals(await eventsDB.count([{ kinds: [0], authors: [event0.pubkey] }]), 1);
|
||||
assertEquals((await eventsDB.count([{ kinds: [0], authors: [event0.pubkey] }])).count, 1);
|
||||
|
||||
const changeEvent = { ...event0, id: '123', created_at: event0.created_at + 1 };
|
||||
await eventsDB.event(changeEvent);
|
||||
|
|
|
@ -345,9 +345,9 @@ class EventsDB implements NStore {
|
|||
}
|
||||
|
||||
/** Get number of events that would be returned by filters. */
|
||||
async count(filters: DittoFilter[], opts: NStoreOpts = {}): Promise<number> {
|
||||
async count(filters: DittoFilter[], opts: NStoreOpts = {}): Promise<{ count: number; approximate: boolean }> {
|
||||
if (opts.signal?.aborted) return Promise.reject(abortError());
|
||||
if (!filters.length) return Promise.resolve(0);
|
||||
if (!filters.length) return Promise.resolve({ count: 0, approximate: false });
|
||||
|
||||
this.#debug('COUNT', JSON.stringify(filters));
|
||||
const query = this.getEventsQuery(filters);
|
||||
|
@ -357,7 +357,10 @@ class EventsDB implements NStore {
|
|||
.select((eb) => eb.fn.count('id').as('count'))
|
||||
.execute();
|
||||
|
||||
return Number(count);
|
||||
return {
|
||||
count: Number(count),
|
||||
approximate: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,14 +94,6 @@ class Optimizer implements NStore {
|
|||
|
||||
return getResults();
|
||||
}
|
||||
|
||||
count(_filters: DittoFilter[]): Promise<number> {
|
||||
return Promise.reject(new Error('COUNT not implemented.'));
|
||||
}
|
||||
|
||||
remove(_filters: DittoFilter[]): Promise<void> {
|
||||
return Promise.reject(new Error('DELETE not implemented.'));
|
||||
}
|
||||
}
|
||||
|
||||
export { Optimizer };
|
||||
|
|
|
@ -92,14 +92,6 @@ class PoolStore implements NStore {
|
|||
opts.signal?.addEventListener('abort', onAbort);
|
||||
});
|
||||
}
|
||||
|
||||
count() {
|
||||
return Promise.reject(new Error('COUNT not implemented'));
|
||||
}
|
||||
|
||||
remove() {
|
||||
return Promise.reject(new Error('Cannot delete events from relays. Create a kind 5 event instead.'));
|
||||
}
|
||||
}
|
||||
|
||||
export { PoolStore };
|
||||
|
|
|
@ -133,14 +133,6 @@ class Reqmeister extends EventEmitter<{ [filterId: string]: (event: NostrEvent)
|
|||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
count(_filters: NostrFilter[]): Promise<number> {
|
||||
return Promise.reject(new Error('COUNT not implemented.'));
|
||||
}
|
||||
|
||||
remove(_filters: NostrFilter[]): Promise<void> {
|
||||
return Promise.reject(new Error('DELETE not implemented.'));
|
||||
}
|
||||
}
|
||||
|
||||
export { Reqmeister };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { NiceRelay } from 'https://gitlab.com/soapbox-pub/nostr-machina/-/raw/5f4fb59c90c092e5aa59c01e6556a4bec264c167/mod.ts';
|
||||
|
||||
import { Debug, type NostrEvent, type NostrFilter, NSet, type NStore, type NStoreOpts } from '@/deps.ts';
|
||||
import { Debug, type NostrEvent, NSet, type NStore, type NStoreOpts } from '@/deps.ts';
|
||||
import { normalizeFilters } from '@/filter.ts';
|
||||
import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||
import { type DittoFilter } from '@/interfaces/DittoFilter.ts';
|
||||
|
@ -68,14 +68,6 @@ class SearchStore implements NStore {
|
|||
return this.#fallback.query(filters, opts);
|
||||
}
|
||||
}
|
||||
|
||||
count(_filters: NostrFilter[]): Promise<number> {
|
||||
return Promise.reject(new Error('COUNT not implemented.'));
|
||||
}
|
||||
|
||||
remove(_filters: NostrFilter[]): Promise<void> {
|
||||
return Promise.reject(new Error('DELETE not implemented.'));
|
||||
}
|
||||
}
|
||||
|
||||
export { SearchStore };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// deno-lint-ignore-file ban-types
|
||||
|
||||
import { LRUCache, type MapCache } from '@/deps.ts';
|
||||
import { LRUCache } from '@/deps.ts';
|
||||
|
||||
type FetchFn<K extends {}, V extends {}, O extends {}> = (key: K, opts: O) => Promise<V>;
|
||||
|
||||
|
@ -12,7 +12,7 @@ export class SimpleLRU<
|
|||
K extends {},
|
||||
V extends {},
|
||||
O extends {} = FetchFnOpts,
|
||||
> implements MapCache<K, V, O> {
|
||||
> {
|
||||
protected cache: LRUCache<K, V, void>;
|
||||
|
||||
constructor(fetchFn: FetchFn<K, V, { signal: AbortSignal }>, opts: LRUCache.Options<K, V, void>) {
|
||||
|
|
Loading…
Reference in New Issue