Improvements to enablePing() & tests (#506)

https://github.com/nbd-wtf/nostr-tools/pull/506
This commit is contained in:
Chris McCormick 2025-09-29 21:41:40 +08:00 committed by GitHub
parent c9ff51e278
commit 226d7d07e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 93 additions and 17 deletions

View File

@ -59,16 +59,24 @@ test('same with double subs', async () => {
let priv = generateSecretKey() let priv = generateSecretKey()
let pub = getPublicKey(priv) let pub = getPublicKey(priv)
pool.subscribeMany(relayURLs, { authors: [pub] }, { pool.subscribeMany(
onevent(event) { relayURLs,
received.push(event) { authors: [pub] },
{
onevent(event) {
received.push(event)
},
}, },
}) )
pool.subscribeMany(relayURLs, { authors: [pub] }, { pool.subscribeMany(
onevent(event) { relayURLs,
received.push(event) { authors: [pub] },
{
onevent(event) {
received.push(event)
},
}, },
}) )
let received: Event[] = [] let received: Event[] = []
@ -172,12 +180,16 @@ test('query a bunch of events and cancel on eose', async () => {
let events = new Set<string>() let events = new Set<string>()
await new Promise<void>(resolve => { await new Promise<void>(resolve => {
pool.subscribeManyEose(relayURLs, { kinds: [0, 1, 2, 3, 4, 5, 6], limit: 40 }, { pool.subscribeManyEose(
onevent(event) { relayURLs,
events.add(event.id) { kinds: [0, 1, 2, 3, 4, 5, 6], limit: 40 },
{
onevent(event) {
events.add(event.id)
},
onclose: resolve as any,
}, },
onclose: resolve as any, )
})
}) })
expect(events.size).toBeGreaterThan(50) expect(events.size).toBeGreaterThan(50)
@ -210,6 +222,37 @@ test('get()', async () => {
expect(event).toHaveProperty('id', ids[0]) expect(event).toHaveProperty('id', ids[0])
}) })
test('ping-pong timeout in pool', async () => {
const mockRelay = mockRelays[0]
pool = new SimplePool({ enablePing: true })
const relay = await pool.ensureRelay(mockRelay.url)
relay.pingTimeout = 50
relay.pingFrequency = 50
let closed = false
const closedPromise = new Promise<void>(resolve => {
relay.onclose = () => {
closed = true
resolve()
}
})
expect(relay.connected).toBeTrue()
// wait for the first ping to succeed
await new Promise(resolve => setTimeout(resolve, 75))
expect(closed).toBeFalse()
// now make it unresponsive
mockRelay.unresponsive = true
// wait for the second ping to fail
await closedPromise
expect(relay.connected).toBeFalse()
expect(closed).toBeTrue()
})
test('track relays when publishing', async () => { test('track relays when publishing', async () => {
let event1 = finalizeEvent( let event1 = finalizeEvent(
{ {

View File

@ -117,3 +117,34 @@ test('publish timeout', async () => {
), ),
).rejects.toThrow('publish timed out') ).rejects.toThrow('publish timed out')
}) })
test('ping-pong timeout', async () => {
const mockRelay = new MockRelay()
const relay = new Relay(mockRelay.url, { enablePing: true })
relay.pingTimeout = 50
relay.pingFrequency = 50
let closed = false
const closedPromise = new Promise<void>(resolve => {
relay.onclose = () => {
closed = true
resolve()
}
})
await relay.connect()
expect(relay.connected).toBeTrue()
// wait for the first ping to succeed
await new Promise(resolve => setTimeout(resolve, 75))
expect(closed).toBeFalse()
// now make it unresponsive
mockRelay.unresponsive = true
// wait for the second ping to fail
await closedPromise
expect(relay.connected).toBeFalse()
expect(closed).toBeTrue()
})

View File

@ -14,12 +14,12 @@ export function useWebSocketImplementation(websocketImplementation: any) {
} }
export class Relay extends AbstractRelay { export class Relay extends AbstractRelay {
constructor(url: string) { constructor(url: string, options?: { enablePing?: boolean }) {
super(url, { verifyEvent, websocketImplementation: _WebSocket }) super(url, { verifyEvent, websocketImplementation: _WebSocket, ...options })
} }
static async connect(url: string): Promise<Relay> { static async connect(url: string, options?: { enablePing?: boolean }): Promise<Relay> {
const relay = new Relay(url) const relay = new Relay(url, options)
await relay.connect() await relay.connect()
return relay return relay
} }

View File

@ -26,6 +26,7 @@ export class MockRelay {
public url: string public url: string
public secretKeys: Uint8Array[] public secretKeys: Uint8Array[]
public preloadedEvents: Event[] public preloadedEvents: Event[]
public unresponsive: boolean = false
constructor(url?: string | undefined) { constructor(url?: string | undefined) {
serial++ serial++
@ -48,6 +49,7 @@ export class MockRelay {
let subs: { [subId: string]: { conn: any; filters: Filter[] } } = {} let subs: { [subId: string]: { conn: any; filters: Filter[] } } = {}
conn.on('message', (message: string) => { conn.on('message', (message: string) => {
if (this.unresponsive) return
const data = JSON.parse(message) const data = JSON.parse(message)
switch (data[0]) { switch (data[0]) {