From d2ef0ac3b192f1cc474d380333fba85c9fc8fab7 Mon Sep 17 00:00:00 2001 From: William Casarin Date: Mon, 18 May 2026 11:46:57 -0700 Subject: [PATCH] relay: fix relays refusing to reconnect after initial connect fails When isConnecting gets stuck (e.g. from silenced error 57 or lost WebSocket events), reconnect() would bail out permanently. Instead of unconditionally blocking on isConnecting, allow reconnect if the connection attempt has gone stale (>5s with no socket response). Closes: https://github.com/damus-io/damus/issues/3774 Co-Authored-By: Claude Opus 4.6 --- damus/Core/Nostr/RelayConnection.swift | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/damus/Core/Nostr/RelayConnection.swift b/damus/Core/Nostr/RelayConnection.swift index 0f913757..a486db36 100644 --- a/damus/Core/Nostr/RelayConnection.swift +++ b/damus/Core/Nostr/RelayConnection.swift @@ -114,7 +114,7 @@ final class RelayConnection: ObservableObject { guard let self else { return } - + if err == nil { self.last_pong = .now Log.info("Got pong from '%s'", for: .networking, self.relay_url.absoluteString) @@ -214,7 +214,7 @@ final class RelayConnection: ObservableObject { return } if nserr.domain == NSURLErrorDomain && nserr.code == -999 { - // these aren't real error, it just means task was cancelled + // these aren't real errors, it just means task was cancelled return } DispatchQueue.main.async { @@ -237,9 +237,9 @@ final class RelayConnection: ObservableObject { } func reconnect() { - guard !isConnecting && !isDisabled else { - self.log?.add("Cancelling reconnect, already connecting") - return // we're already trying to connect or we're disabled + guard !isDisabled else { + self.log?.add("Cancelling reconnect, relay is disabled") + return } guard !self.isConnected else { @@ -247,6 +247,17 @@ final class RelayConnection: ObservableObject { return } + // If we're already connecting, only force a reconnect if the + // attempt has gone stale (>5s with no response from the socket) + if isConnecting { + let elapsed = Date.now.timeIntervalSince1970 - last_connection_attempt + guard elapsed > 5 else { + self.log?.add("Cancelling reconnect, already connecting") + return + } + self.log?.add("Stale connection detected, forcing reconnect") + } + disconnect() connect() log?.add("Reconnecting...")