fix(bridge): resolve websocket zombie connection and bounding memory leaks
This commit is contained in:
@@ -122,6 +122,7 @@ export class WSBridgeClient {
|
||||
private reconnectDelay = INITIAL_RECONNECT_DELAY;
|
||||
private reconnectTimer: NodeJS.Timeout | null = null;
|
||||
private heartbeatTimer: NodeJS.Timeout | null = null;
|
||||
private pongTimeoutTimer: NodeJS.Timeout | null = null;
|
||||
private authTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
// Message queue (survives reconnection)
|
||||
@@ -245,6 +246,10 @@ export class WSBridgeClient {
|
||||
|
||||
ws.on('pong', () => {
|
||||
// Server responded to our ping — connection is alive
|
||||
if (this.pongTimeoutTimer) {
|
||||
clearTimeout(this.pongTimeoutTimer);
|
||||
this.pongTimeoutTimer = null;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// ─── Browser-style WebSocket API (.onopen / .onmessage) ───
|
||||
@@ -469,6 +474,16 @@ export class WSBridgeClient {
|
||||
// Node.js ws has .ping(), browser WebSocket doesn't
|
||||
if (typeof this.ws.ping === 'function') {
|
||||
this.ws.ping();
|
||||
|
||||
// Set timeout waiting for pong
|
||||
if (this.pongTimeoutTimer) clearTimeout(this.pongTimeoutTimer);
|
||||
this.pongTimeoutTimer = setTimeout(() => {
|
||||
this.logFn('[WS] Heartbeat timeout — no pong received, terminating connection');
|
||||
if (this.ws) {
|
||||
try { this.ws.terminate(); } catch { try { this.ws.close(); } catch { } }
|
||||
}
|
||||
this._onDisconnect();
|
||||
}, 10000); // 10s timeout
|
||||
} else {
|
||||
// Fallback: send heartbeat as JSON message
|
||||
this.ws.send(JSON.stringify({ type: 'heartbeat' }));
|
||||
@@ -485,6 +500,10 @@ export class WSBridgeClient {
|
||||
clearInterval(this.heartbeatTimer);
|
||||
this.heartbeatTimer = null;
|
||||
}
|
||||
if (this.pongTimeoutTimer) {
|
||||
clearTimeout(this.pongTimeoutTimer);
|
||||
this.pongTimeoutTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Reconnection ───
|
||||
@@ -540,6 +559,11 @@ export class WSBridgeClient {
|
||||
this.reconnectTimer = null;
|
||||
}
|
||||
|
||||
if (this.pongTimeoutTimer) {
|
||||
clearTimeout(this.pongTimeoutTimer);
|
||||
this.pongTimeoutTimer = null;
|
||||
}
|
||||
|
||||
if (this.ws) {
|
||||
try {
|
||||
this.ws.close();
|
||||
|
||||
Reference in New Issue
Block a user