From 79e38b8f794a4b2539a67559ca7067dd2c3c8b26 Mon Sep 17 00:00:00 2001 From: Laan Tungir Date: Tue, 30 Jun 2026 10:11:08 -0400 Subject: [PATCH] Experiment: increase per-relay broadcast timeout to 60s to test if NDK can handle 600 relays with longer connection time --- www/js/version.json | 6 +++--- www/ndk-worker.js | 26 ++++++++++++++------------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/www/js/version.json b/www/js/version.json index 97f9f65..14e13dc 100644 --- a/www/js/version.json +++ b/www/js/version.json @@ -1,5 +1,5 @@ { - "VERSION": "v0.7.74", - "VERSION_NUMBER": "0.7.74", - "BUILD_DATE": "2026-06-30T14:06:37.971Z" + "VERSION": "v0.7.75", + "VERSION_NUMBER": "0.7.75", + "BUILD_DATE": "2026-06-30T14:11:08.103Z" } diff --git a/www/ndk-worker.js b/www/ndk-worker.js index ae095b5..f4678c2 100644 --- a/www/ndk-worker.js +++ b/www/ndk-worker.js @@ -6205,14 +6205,15 @@ async function handlePublish(requestId, event, port) { if (NDKRelaySet?.fromRelayUrls) { targetRelaySet = NDKRelaySet.fromRelayUrls(allUrls, ndk); // 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. + // the per-relay publish timeout. NDK's default + // connectionTimeout is 4400ms — we increase it so relays have + // time to connect even when hundreds are competing for browser + // connection slots. if (targetRelaySet?.relays) { for (const relay of targetRelaySet.relays) { try { if (relay.connectionTimeout !== undefined) { - relay.connectionTimeout = 5000; + relay.connectionTimeout = 60000; } } catch (_) { /* relay may be read-only */ } } @@ -6295,12 +6296,13 @@ async function handlePublish(requestId, event, port) { } // Publish to relays (with broadcast relay set if broadcasting, else default outbox). - // 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. + // Per-relay timeout for broadcasts: 60 seconds. NDK may not be able to handle + // hundreds of simultaneous WebSocket connections in true parallel — the browser + // has connection limits and NDK's pool may serialize some operations. A 60s + // per-relay timeout gives each relay ample time to connect and publish even when + // queued behind hundreds of others. // requiredRelayCount=1 so NDK doesn't throw if only 1 of 600 relays succeeds. - const BROADCAST_PER_RELAY_TIMEOUT_MS = 5000; + const BROADCAST_PER_RELAY_TIMEOUT_MS = 60000; const publishTimeoutMs = isBroadcast ? BROADCAST_PER_RELAY_TIMEOUT_MS : undefined; const publishRequiredCount = isBroadcast ? 1 : undefined; @@ -6309,9 +6311,9 @@ async function handlePublish(requestId, event, port) { // 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. + // as a safety cap. With 600 relays × 60s = 36000s (10 hours) — this is + // effectively "wait until all relays finish" since the deadline will never + // fire before the per-relay timeouts resolve all promises. const BROADCAST_OVERALL_DEADLINE_MS = Math.max(30000, totalTarget * BROADCAST_PER_RELAY_TIMEOUT_MS); const publishPromise = ndkEvent.publish(targetRelaySet, publishTimeoutMs, publishRequiredCount) .catch((err) => {