From f8be7288426175f1ff1c14d73987222e41472af2 Mon Sep 17 00:00:00 2001 From: Nicolas Varrot Date: Wed, 11 Feb 2026 22:33:02 +0000 Subject: [PATCH] fix: use exponential backoff with jitter for WebSocket reconnection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace fixed 3s reconnect delay with exponential backoff (1s → 30s cap) plus 30% jitter to prevent thundering herd. Resets on successful connection or manual disconnect. --- src/lib/gateway.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/lib/gateway.ts b/src/lib/gateway.ts index 2f6d001..26588ea 100644 --- a/src/lib/gateway.ts +++ b/src/lib/gateway.ts @@ -24,6 +24,7 @@ export class GatewayClient { private eventHandlers: GatewayEventHandler[] = []; private _onStatus: (s: 'disconnected' | 'connecting' | 'connected') => void = () => {}; private reconnectTimer: ReturnType | null = null; + private reconnectAttempts = 0; private connected = false; private autoReconnect = true; @@ -109,6 +110,7 @@ export class GatewayClient { }).then((res) => { console.log('[GW] connected!', res); this.connected = true; + this.reconnectAttempts = 0; this._onStatus('connected'); }).catch((err) => { console.log('[GW] connect failed:', err); @@ -119,14 +121,20 @@ export class GatewayClient { private scheduleReconnect() { if (this.reconnectTimer) return; + const base = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000); + const jitter = Math.random() * base * 0.3; + const delay = base + jitter; + this.reconnectAttempts++; + console.log(`[GW] reconnecting in ${Math.round(delay)}ms (attempt ${this.reconnectAttempts})`); this.reconnectTimer = setTimeout(() => { this.reconnectTimer = null; this.connect(); - }, 3000); + }, delay); } disconnect() { this.autoReconnect = false; + this.reconnectAttempts = 0; if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null; } if (this.ws) { this.ws.close(); this.ws = null; } this.connected = false;