From da59e3ce90da3526736c3e57a852774ea07fc851 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Wed, 8 Feb 2023 09:46:05 -0300 Subject: [PATCH] when in pool, automatically and efficiently deduplicate. --- pool.test.js | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ pool.ts | 11 +++++++ relay.ts | 2 +- 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 pool.test.js diff --git a/pool.test.js b/pool.test.js new file mode 100644 index 0000000..4dda7f7 --- /dev/null +++ b/pool.test.js @@ -0,0 +1,84 @@ +/* eslint-env jest */ + +require('websocket-polyfill') +const { + pool, + generatePrivateKey, + getPublicKey, + getEventHash, + signEvent +} = require('./lib/nostr.cjs') + +let p = pool() + +let relays = [ + p.ensureRelay('wss://nostr-dev.wellorder.net/'), + p.ensureRelay('wss://relay.nostr.bg/'), + p.ensureRelay('wss://nostr.fmt.wiz.biz/'), + p.ensureRelay('wss://relay.nostr.band/'), + p.ensureRelay('wss://nostr.zebedee.cloud/') +] + +beforeAll(async () => { + Promise.all( + relays.map(relay => { + try { + return relay.connect() + } catch (err) { + /***/ + } + }) + ) +}) + +afterAll(async () => { + relays.forEach(relay => { + try { + relay.close() + } catch (err) { + /***/ + } + }) +}) + +test('removing duplicates when querying', async () => { + let priv = generatePrivateKey() + let pub = getPublicKey(priv) + + let subs = relays.map(relay => + relay.sub([ + { + authors: [pub] + } + ]) + ) + + let received = [] + + subs.forEach(sub => + sub.on('event', event => { + // this should be called only once even though we're listening + // to multiple relays because the events will be catched and + // deduplicated efficiently (without even being parsed) + received.push(event) + }) + ) + + let event = { + pubkey: pub, + created_at: Math.round(Date.now() / 1000), + content: 'test', + kind: 22345, + tags: [] + } + event.id = getEventHash(event) + event.sig = signEvent(event, priv) + + relays.forEach(relay => { + relay.publish(event) + }) + + await new Promise(resolve => setTimeout(resolve, 1500)) + + return expect(received).toHaveLength(1) +}) diff --git a/pool.ts b/pool.ts index 2883254..012b058 100644 --- a/pool.ts +++ b/pool.ts @@ -1,5 +1,8 @@ import {Relay, relayInit} from './relay' import {normalizeURL} from './utils' +import {Filter} from './filter' +import {Event} from './event' +import {SubscriptionOptions, Sub} from './relay' export function pool(defaultRelays: string[] = []) { return new SimplePool(defaultRelays) @@ -22,6 +25,14 @@ class SimplePool { const hasEventId = (id: string): boolean => this._knownIds.has(id) const relay = relayInit(nm, hasEventId) this._conn[nm] = relay + + let sub = relay.sub + relay.sub = (filters: Filter[], opts?: SubscriptionOptions): Sub => { + let s = sub(filters, opts) + s.on('event', (event: Event) => this._knownIds.add(event.id as string)) + return s + } + return relay } } diff --git a/relay.ts b/relay.ts index 42130b4..2cf05dd 100644 --- a/relay.ts +++ b/relay.ts @@ -27,7 +27,7 @@ export type Sub = { off: (type: 'event' | 'eose', cb: any) => void } -type SubscriptionOptions = { +export type SubscriptionOptions = { skipVerification?: boolean id?: string }