mirror of
https://github.com/nbd-wtf/nostr-tools.git
synced 2025-12-09 00:28:51 +00:00
improvements and fixes on pool.
This commit is contained in:
139
pool.ts
139
pool.ts
@@ -12,7 +12,16 @@ export class SimplePool {
|
||||
defaultRelays.forEach(this.ensureRelay)
|
||||
}
|
||||
|
||||
ensureRelay(url: string): Relay {
|
||||
async close(relays: string[]): Promise<void> {
|
||||
await Promise.all(
|
||||
relays.map(async url => {
|
||||
let relay = this._conn[normalizeURL(url)]
|
||||
if (relay) await relay.close()
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async ensureRelay(url: string): Promise<Relay> {
|
||||
const nm = normalizeURL(url)
|
||||
const existing = this._conn[nm]
|
||||
if (existing) return existing
|
||||
@@ -20,21 +29,74 @@ export class SimplePool {
|
||||
const relay = relayInit(nm)
|
||||
this._conn[nm] = relay
|
||||
|
||||
await relay.connect()
|
||||
|
||||
return relay
|
||||
}
|
||||
|
||||
sub(relays: string[], filters: Filter[], opts?: SubscriptionOptions): Sub[] {
|
||||
sub(relays: string[], filters: Filter[], opts?: SubscriptionOptions): Sub {
|
||||
let _knownIds: Set<string> = new Set()
|
||||
let modifiedOpts = opts || {}
|
||||
modifiedOpts.alreadyHaveEvent = id => _knownIds.has(id)
|
||||
|
||||
return relays.map(relay => {
|
||||
let r = this._conn[relay]
|
||||
if (!r) return badSub()
|
||||
let subs: Sub[] = []
|
||||
let eventListeners: Set<(event: Event) => void> = new Set()
|
||||
let eoseListeners: Set<() => void> = new Set()
|
||||
let eosesMissing = relays.length
|
||||
|
||||
let eoseSent = false
|
||||
let eoseTimeout = setTimeout(() => {
|
||||
eoseSent = true
|
||||
for (let cb of eoseListeners.values()) {
|
||||
cb()
|
||||
}
|
||||
}, 2400)
|
||||
|
||||
relays.forEach(async relay => {
|
||||
let r = await this.ensureRelay(relay)
|
||||
if (!r) return
|
||||
let s = r.sub(filters, modifiedOpts)
|
||||
s.on('event', (event: Event) => _knownIds.add(event.id as string))
|
||||
return s
|
||||
s.on('event', (event: Event) => {
|
||||
_knownIds.add(event.id as string)
|
||||
for (let cb of eventListeners.values()) {
|
||||
cb(event)
|
||||
}
|
||||
})
|
||||
s.on('eose', () => {
|
||||
if (eoseSent) return
|
||||
|
||||
eosesMissing--
|
||||
if (eosesMissing === 0) {
|
||||
clearTimeout(eoseTimeout)
|
||||
for (let cb of eoseListeners.values()) {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
})
|
||||
subs.push(s)
|
||||
})
|
||||
|
||||
let greaterSub: Sub = {
|
||||
sub(filters, opts) {
|
||||
subs.forEach(sub => sub.sub(filters, opts))
|
||||
return greaterSub
|
||||
},
|
||||
unsub() {
|
||||
subs.forEach(sub => sub.unsub())
|
||||
},
|
||||
on(type, cb) {
|
||||
if (type === 'event') {
|
||||
eventListeners.add(cb)
|
||||
} else if (type === 'eose') eoseListeners.add(cb)
|
||||
},
|
||||
off(type, cb) {
|
||||
if (type === 'event') {
|
||||
eventListeners.delete(cb)
|
||||
} else if (type === 'eose') eoseListeners.delete(cb)
|
||||
}
|
||||
}
|
||||
|
||||
return greaterSub
|
||||
}
|
||||
|
||||
get(
|
||||
@@ -43,19 +105,15 @@ export class SimplePool {
|
||||
opts?: SubscriptionOptions
|
||||
): Promise<Event | null> {
|
||||
return new Promise(resolve => {
|
||||
let subs = this.sub(relays, [filter], opts)
|
||||
let sub = this.sub(relays, [filter], opts)
|
||||
let timeout = setTimeout(() => {
|
||||
subs.forEach(sub => sub.unsub(), 1500)
|
||||
sub.unsub()
|
||||
resolve(null)
|
||||
})
|
||||
subs.forEach(sub => {
|
||||
sub.on('event', (event: Event) => {
|
||||
resolve(event)
|
||||
clearTimeout(timeout)
|
||||
subs.forEach(sub => {
|
||||
sub.unsub()
|
||||
})
|
||||
})
|
||||
}, 1500)
|
||||
sub.on('event', (event: Event) => {
|
||||
resolve(event)
|
||||
clearTimeout(timeout)
|
||||
sub.unsub()
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -66,42 +124,24 @@ export class SimplePool {
|
||||
opts?: SubscriptionOptions
|
||||
): Promise<Event[]> {
|
||||
return new Promise(resolve => {
|
||||
let _knownIds: Set<string> = new Set()
|
||||
let modifiedOpts = opts || {}
|
||||
modifiedOpts.alreadyHaveEvent = id => _knownIds.has(id)
|
||||
|
||||
let events: Event[] = []
|
||||
let sub = this.sub(relays, filters, opts)
|
||||
|
||||
let subs = this.sub(relays, filters, modifiedOpts)
|
||||
let timeout = setTimeout(() => {
|
||||
subs.forEach(sub => sub.unsub(), 1500)
|
||||
resolve(events)
|
||||
sub.on('event', (event: Event) => {
|
||||
events.push(event)
|
||||
})
|
||||
|
||||
let pendingEoses = relays.length
|
||||
|
||||
subs.forEach(sub => {
|
||||
sub.on('event', (event: Event) => {
|
||||
events.push(event)
|
||||
})
|
||||
|
||||
sub.on('eose', () => {
|
||||
pendingEoses--
|
||||
if (pendingEoses === 0) {
|
||||
resolve(events)
|
||||
clearTimeout(timeout)
|
||||
subs.forEach(sub => {
|
||||
sub.unsub()
|
||||
})
|
||||
}
|
||||
})
|
||||
// we can rely on an eose being emitted here because pool.sub() will fake one
|
||||
sub.on('eose', () => {
|
||||
sub.unsub()
|
||||
resolve(events)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
publish(relays: string[], event: Event): Pub[] {
|
||||
return relays.map(relay => {
|
||||
let r = this._conn[relay]
|
||||
let r = this._conn[normalizeURL(relay)]
|
||||
if (!r) return badPub(relay)
|
||||
let s = r.publish(event)
|
||||
return s
|
||||
@@ -109,17 +149,6 @@ export class SimplePool {
|
||||
}
|
||||
}
|
||||
|
||||
function badSub(): Sub {
|
||||
return {
|
||||
on() {},
|
||||
off() {},
|
||||
sub(): Sub {
|
||||
return badSub()
|
||||
},
|
||||
unsub() {}
|
||||
}
|
||||
}
|
||||
|
||||
function badPub(relay: string): Pub {
|
||||
return {
|
||||
on(typ, cb) {
|
||||
|
||||
Reference in New Issue
Block a user