From 4b5a48425946956110fdf9690ce475fb5db66c96 Mon Sep 17 00:00:00 2001 From: Asai Toshiya Date: Wed, 30 Oct 2024 22:37:49 +0900 Subject: [PATCH] make publish() timeout. --- abstract-relay.ts | 16 +++++++++++++--- relay.test.ts | 27 ++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/abstract-relay.ts b/abstract-relay.ts index 55fc045..86884e4 100644 --- a/abstract-relay.ts +++ b/abstract-relay.ts @@ -24,6 +24,7 @@ export class AbstractRelay { public baseEoseTimeout: number = 4400 public connectionTimeout: number = 4400 + public publishTimeout: number = 4400 public openSubs: Map = new Map() private connectionTimeoutHandle: ReturnType | undefined @@ -198,9 +199,11 @@ export class AbstractRelay { const ok: boolean = data[2] const reason: string = data[3] const ep = this.openEventPublishes.get(id) as EventPublishResolver - if (ok) ep.resolve(reason) - else ep.reject(new Error(reason)) - this.openEventPublishes.delete(id) + if (ep) { + if (ok) ep.resolve(reason) + else ep.reject(new Error(reason)) + this.openEventPublishes.delete(id) + } return } case 'CLOSED': { @@ -248,6 +251,13 @@ export class AbstractRelay { this.openEventPublishes.set(event.id, { resolve, reject }) }) this.send('["EVENT",' + JSON.stringify(event) + ']') + setTimeout(() => { + const ep = this.openEventPublishes.get(event.id) as EventPublishResolver + if (ep) { + ep.reject(new Error('publish timed out')) + this.openEventPublishes.delete(event.id) + } + }, this.publishTimeout) return ret } diff --git a/relay.test.ts b/relay.test.ts index fde6982..0522297 100644 --- a/relay.test.ts +++ b/relay.test.ts @@ -1,5 +1,5 @@ import { expect, test } from 'bun:test' - +import { Server } from 'mock-socket' import { finalizeEvent, generateSecretKey, getPublicKey } from './pure.ts' import { Relay, useWebSocketImplementation } from './relay.ts' import { MockRelay, MockWebSocketClient } from './test-helpers.ts' @@ -92,3 +92,28 @@ test('listening and publishing and closing', async done => { ), ) }) + +test('publish timeout', async () => { + const url = 'wss://relay.example.com' + new Server(url) + + const relay = new Relay(url) + relay.publishTimeout = 100 + await relay.connect() + + setTimeout(() => relay.close(), 20000) // close the relay to fail the test on timeout + + expect( + relay.publish( + finalizeEvent( + { + kind: 1, + created_at: Math.floor(Date.now() / 1000), + tags: [], + content: 'hello', + }, + generateSecretKey(), + ), + ), + ).rejects.toThrow('publish timed out') +})