From 7cfd43b91b6754c36c9393ef9ea5d15ed1620144 Mon Sep 17 00:00:00 2001 From: Laan Tungir Date: Tue, 30 Jun 2026 10:06:37 -0400 Subject: [PATCH] Set per-relay broadcast timeout to 5s, overall deadline to totalRelays*5s (min 30s). NDK runs relays in parallel so 600 relays finish in ~5s not 3000s --- www/js/version.json | 6 +++--- www/ndk-worker.js | 36 +++++++++++++++++------------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/www/js/version.json b/www/js/version.json index fa859c7..97f9f65 100644 --- a/www/js/version.json +++ b/www/js/version.json @@ -1,5 +1,5 @@ { - "VERSION": "v0.7.73", - "VERSION_NUMBER": "0.7.73", - "BUILD_DATE": "2026-06-30T14:02:00.201Z" + "VERSION": "v0.7.74", + "VERSION_NUMBER": "0.7.74", + "BUILD_DATE": "2026-06-30T14:06:37.971Z" } diff --git a/www/ndk-worker.js b/www/ndk-worker.js index 57b5200..ae095b5 100644 --- a/www/ndk-worker.js +++ b/www/ndk-worker.js @@ -6204,17 +6204,15 @@ async function handlePublish(requestId, event, port) { const allUrls = [...new Set([...outboxWriteUrls, ...activeBroadcastUrls])]; if (NDKRelaySet?.fromRelayUrls) { targetRelaySet = NDKRelaySet.fromRelayUrls(allUrls, ndk); - // Increase the connection timeout on all relays in the set. - // NDK's default connectionTimeout is 4400ms, which is too short - // for hundreds of temporary broadcast relays that need to - // establish WebSocket connections. Give them 15s to connect. - // The publish timeout (30s below) covers the full connect+publish - // cycle per relay. + // Set the connection timeout on all relays in the set to match + // the per-relay publish timeout (5s). NDK's default + // connectionTimeout is 4400ms — we set it to 5000ms so the + // connection attempt and publish share the same 5s budget. if (targetRelaySet?.relays) { for (const relay of targetRelaySet.relays) { try { if (relay.connectionTimeout !== undefined) { - relay.connectionTimeout = 15000; + relay.connectionTimeout = 5000; } } catch (_) { /* relay may be read-only */ } } @@ -6297,24 +6295,24 @@ async function handlePublish(requestId, event, port) { } // Publish to relays (with broadcast relay set if broadcasting, else default outbox). - // When broadcasting to many relays (potentially hundreds), use a much longer - // per-relay timeout than NDK's default 4400ms — temporary relays need time to - // establish WebSocket connections. Use 30s per relay for broadcasts. + // Per-relay timeout for broadcasts: 5 seconds. This covers both the WebSocket + // connection attempt and the publish OK response for each relay. NDK runs all + // relay publishes in parallel via Promise.all, so with 600 relays the overall + // time is ~5s (the slowest relay), not 600×5s. // requiredRelayCount=1 so NDK doesn't throw if only 1 of 600 relays succeeds. - const BROADCAST_PER_RELAY_TIMEOUT_MS = 30000; + const BROADCAST_PER_RELAY_TIMEOUT_MS = 5000; const publishTimeoutMs = isBroadcast ? BROADCAST_PER_RELAY_TIMEOUT_MS : undefined; const publishRequiredCount = isBroadcast ? 1 : undefined; let relaySet; if (isBroadcast) { - // For broadcasts, don't await the full Promise.all — NDK's publish() - // waits for ALL relays to resolve, so one slow relay blocks the entire - // operation. Instead, race the publish against an overall deadline. - // The live progress listeners (relay:published / relay:publish:failed) - // already track per-relay results in real time, so we can resolve early - // once the deadline hits. Relays that haven't responded by the deadline - // are simply not counted — they may still complete in the background. - const BROADCAST_OVERALL_DEADLINE_MS = 45000; // 45s overall cap + // For broadcasts, race the publish against an overall deadline. + // NDK's publish() uses Promise.all internally, so it waits for ALL + // relays to resolve. The overall deadline is totalRelays × perRelayTimeout + // as a safety cap — in practice all relays run in parallel so the publish + // should complete in ~perRelayTimeout, but the deadline ensures we never + // hang indefinitely if something goes wrong. + const BROADCAST_OVERALL_DEADLINE_MS = Math.max(30000, totalTarget * BROADCAST_PER_RELAY_TIMEOUT_MS); const publishPromise = ndkEvent.publish(targetRelaySet, publishTimeoutMs, publishRequiredCount) .catch((err) => { // NDKPublishError is expected when not all relays succeed —