Fix relay client reconnect self-replacement

This commit is contained in:
Mohamed Boudra
2026-02-05 09:00:01 +07:00
parent dc5336660b
commit 32f32051d0
+18 -10
View File
@@ -337,7 +337,11 @@ export class DaemonClient {
} }
try { try {
this.cleanupTransport(); // If we reconnect while the previous socket is still open (common in browsers
// where `onerror` may fire before `onclose`), we can end up with multiple
// concurrent relay sockets. Cloudflare then closes the old one with
// "Replaced by new connection", causing a disconnect loop.
this.disposeTransport();
const baseTransportFactory = const baseTransportFactory =
this.config.transportFactory ?? this.config.transportFactory ??
createWebSocketTransportFactory( createWebSocketTransportFactory(
@@ -465,15 +469,7 @@ export class DaemonClient {
clearTimeout(this.reconnectTimeout); clearTimeout(this.reconnectTimeout);
this.reconnectTimeout = null; this.reconnectTimeout = null;
} }
this.cleanupTransport(); this.disposeTransport(1000, "Client closed");
if (this.transport) {
try {
this.transport.close();
} catch {
// no-op
}
this.transport = null;
}
this.clearWaiters(new Error("Daemon client closed")); this.clearWaiters(new Error("Daemon client closed"));
this.updateConnectionState({ this.updateConnectionState({
status: "disconnected", status: "disconnected",
@@ -2297,6 +2293,18 @@ export class DaemonClient {
return requestId ?? crypto.randomUUID(); return requestId ?? crypto.randomUUID();
} }
private disposeTransport(code = 1001, reason = "Reconnecting"): void {
this.cleanupTransport();
if (this.transport) {
try {
this.transport.close(code, reason);
} catch {
// no-op
}
this.transport = null;
}
}
private cleanupTransport(): void { private cleanupTransport(): void {
if (this.pendingGenericTransportErrorTimeout) { if (this.pendingGenericTransportErrorTimeout) {
clearTimeout(this.pendingGenericTransportErrorTimeout); clearTimeout(this.pendingGenericTransportErrorTimeout);