Skip to content

Commit 33e7595

Browse files
committed
fix(relay): fix reconnection after sleep/wake and stale connections
The relay reconnection logic had a bug where stale connections detected after system sleep/wake would not trigger reconnection: 1. handleStaleConnection() set status to DISCONNECTED before calling onDisconnect(), so when onDisconnect() checked if status was CONNECTED, it was already DISCONNECTED and wouldn't call handleReconnection() 2. Removed MAX_RECONNECT_ATTEMPTS limit (was 5) - relays now retry indefinitely with capped backoff (max 30 seconds between attempts) The fix makes handleStaleConnection() directly call handleReconnection() after cleaning up the dead WebSocket, ensuring reconnection is always attempted when a stale connection is detected.
1 parent c8ab6d9 commit 33e7595

File tree

1 file changed

+24
-13
lines changed

1 file changed

+24
-13
lines changed

core/src/relay/connectivity.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { NDKRelayStatus } from ".";
99
import { NDKRelayKeepalive, probeRelayConnection } from "./keepalive";
1010
import type { NDKRelaySubscription } from "./subscription";
1111

12-
const MAX_RECONNECT_ATTEMPTS = 5;
12+
// Removed MAX_RECONNECT_ATTEMPTS - we retry indefinitely with capped backoff
1313
const FLAPPING_THRESHOLD_MS = 1000;
1414

1515
export type CountResolver = {
@@ -117,12 +117,29 @@ export class NDKRelayConnectivity {
117117
}
118118

119119
/**
120-
* Handles detection of a stale connection
120+
* Handles detection of a stale connection by cleaning up and triggering reconnection.
121121
*/
122122
private handleStaleConnection(): void {
123-
this._status = NDKRelayStatus.DISCONNECTED;
124123
this.wasIdle = true; // Mark as idle to reset backoff
125-
this.onDisconnect();
124+
125+
// Stop keepalive
126+
this.keepalive?.stop();
127+
128+
// Clean up the dead WebSocket
129+
if (this.ws) {
130+
try {
131+
this.ws.close();
132+
} catch (e) {
133+
// Ignore errors closing dead socket
134+
}
135+
this.ws = undefined;
136+
}
137+
138+
this._status = NDKRelayStatus.DISCONNECTED;
139+
this.ndkRelay.emit("disconnect");
140+
141+
// Trigger reconnection for stale connections
142+
this.handleReconnection();
126143
}
127144

128145
/**
@@ -668,15 +685,9 @@ export class NDKRelayConnectivity {
668685
this.reconnectTimeout = undefined;
669686
this._status = NDKRelayStatus.RECONNECTING;
670687

671-
this.connect().catch((_err) => {
672-
if (attempt < MAX_RECONNECT_ATTEMPTS) {
673-
// Continue with next attempt
674-
this.handleReconnection(attempt + 1);
675-
} else {
676-
this.debug("Max reconnect attempts reached");
677-
// Reset idle flag after max attempts
678-
this.wasIdle = false;
679-
}
688+
this.connect().catch(() => {
689+
// Always keep retrying with backoff
690+
this.handleReconnection(attempt + 1);
680691
});
681692
}, reconnectDelay);
682693

0 commit comments

Comments
 (0)