change the way eose and connection timeouts work.

This commit is contained in:
fiatjaf
2023-12-18 17:11:16 -03:00
parent 965ebdb6d1
commit 804403f574
3 changed files with 85 additions and 49 deletions

50
pool.ts
View File

@@ -1,4 +1,4 @@
import { relayConnect, type Relay, SubscriptionParams, Subscription } from './relay.ts'
import { Relay, SubscriptionParams, Subscription } from './relay.ts'
import { normalizeURL } from './utils.ts'
import type { Event } from './event.ts'
@@ -7,7 +7,7 @@ import { type Filter } from './filter.ts'
export type SubCloser = { close: () => void }
export type SubscribeManyParams = Omit<SubscriptionParams, 'onclose' | 'id'> & {
eoseSubTimeout?: number
maxWait?: number
onclose?: (reasons: string[]) => void
id?: string
}
@@ -17,13 +17,18 @@ export class SimplePool {
public seenOn = new Map<string, Set<Relay>>()
public trackRelays: boolean = false
async ensureRelay(url: string): Promise<Relay> {
public trustedRelayURLs = new Set<string>()
async ensureRelay(url: string, params?: { connectionTimeout?: number }): Promise<Relay> {
url = normalizeURL(url)
let relay = this.relays.get(url)
if (!relay) {
relay = relayConnect(url)
relay = new Relay(url)
if (params?.connectionTimeout) relay.connectionTimeout = params.connectionTimeout
if (this.trustedRelayURLs.has(relay.url)) relay.trusted = true
this.relays.set(url, relay)
await relay.connect()
}
return relay
@@ -45,26 +50,22 @@ export class SimplePool {
const subs: Subscription[] = []
// batch all EOSEs into a single
let eosesMissing = relays.length
let handleEose = () => {
eosesMissing--
if (eosesMissing === 0) {
clearTimeout(eoseTimeout)
const eosesReceived: boolean[] = []
let handleEose = (i: number) => {
eosesReceived[i] = true
if (eosesReceived.filter(a => a).length === relays.length) {
params.oneose?.()
handleEose = () => {}
}
}
const eoseTimeout = setTimeout(() => {
handleEose = () => {}
params.oneose?.()
}, params.eoseSubTimeout || 3400)
// batch all closes into a single
const closesReceived: string[] = []
const handleClose = (i: number, reason: string) => {
handleEose()
let handleClose = (i: number, reason: string) => {
handleEose(i)
closesReceived[i] = reason
if (closesReceived.length === relays.length) {
if (closesReceived.filter(a => a).length === relays.length) {
params.onclose?.(closesReceived)
handleClose = () => {}
}
}
@@ -88,17 +89,20 @@ export class SimplePool {
let relay: Relay
try {
relay = await this.ensureRelay(url)
relay = await this.ensureRelay(url, {
connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1000) : undefined,
})
} catch (err) {
handleEose()
handleClose(i, (err as any)?.message || String(err))
return
}
let subscription = await relay.subscribe(filters, {
...params,
oneose: handleEose,
oneose: () => handleEose(i),
onclose: reason => handleClose(i, reason),
alreadyHaveEvent: localAlreadyHaveEventHandler,
eoseTimeout: params.maxWait,
})
subs.push(subscription)
@@ -118,7 +122,7 @@ export class SimplePool {
subscribeManyEose(
relays: string[],
filters: Filter[],
params: Pick<SubscribeManyParams, 'id' | 'onevent' | 'onclose' | 'eoseSubTimeout'>,
params: Pick<SubscribeManyParams, 'id' | 'onevent' | 'onclose' | 'maxWait'>,
): SubCloser {
const subcloser = this.subscribeMany(relays, filters, {
...params,
@@ -132,7 +136,7 @@ export class SimplePool {
async querySync(
relays: string[],
filter: Filter,
params?: Pick<SubscribeManyParams, 'id' | 'eoseSubTimeout'>,
params?: Pick<SubscribeManyParams, 'id' | 'maxWait'>,
): Promise<Event[]> {
return new Promise(async resolve => {
const events: Event[] = []
@@ -151,7 +155,7 @@ export class SimplePool {
async get(
relays: string[],
filter: Filter,
params?: Pick<SubscribeManyParams, 'id' | 'eoseSubTimeout'>,
params?: Pick<SubscribeManyParams, 'id' | 'maxWait'>,
): Promise<Event | null> {
filter.limit = 1
const events = await this.querySync(relays, filter, params)