fix(realtime): guarda cleanup de WebSocket em CONNECTING (StrictMode)

Fechar o socket ainda em CONNECTING (double-mount do StrictMode em dev) gerava
"WebSocket is closed before the connection is established". closeSocket() adia o
close para o onopen e neutraliza handlers; reconexão por queda inesperada intacta.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Builder
2026-07-01 20:54:24 +02:00
parent 3042ddca38
commit 092635be5a
+22 -3
View File
@@ -44,11 +44,30 @@ function connect() {
sock.onerror = () => { try { sock.close(); } catch { /* ignore */ } };
}
// Fecha um socket que NÓS abrimos. Se ainda está em CONNECTING, chamar close()
// agora dispara "WebSocket is closed before the connection is established"
// (comum no double-mount do React StrictMode em DEV) → adiamos o close para o
// onopen. Em todos os casos neutralizamos os handlers para o socket morto não
// disparar reconexão (a reconexão automática por queda inesperada continua no
// onclose original definido em connect()).
function closeSocket(sock: WebSocket | null) {
if (!sock) return;
sock.onmessage = null;
sock.onerror = null;
sock.onclose = null;
if (sock.readyState === WebSocket.CONNECTING) {
sock.onopen = () => { try { sock.close(); } catch { /* ignore */ } };
} else {
sock.onopen = null;
try { sock.close(); } catch { /* ignore */ }
}
}
function ensureConnected() {
const url = buildUrl();
if (!url) return;
// Clínica/token mudou → reconecta no canal certo.
if (ws && url !== currentUrl) { try { ws.close(); } catch { /* ignore */ } ws = null; }
if (ws && url !== currentUrl) { closeSocket(ws); ws = null; }
if (!ws || ws.readyState === WebSocket.CLOSING || ws.readyState === WebSocket.CLOSED) connect();
}
@@ -61,13 +80,13 @@ export const Realtime = {
handlers.delete(handler);
if (handlers.size === 0) {
if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; }
if (ws) { try { ws.close(); } catch { /* ignore */ } ws = null; }
if (ws) { closeSocket(ws); ws = null; }
}
};
},
/** Força reconexão (ex.: ao trocar de workspace). */
reconnect() {
if (ws) { try { ws.close(); } catch { /* ignore */ } ws = null; }
if (ws) { closeSocket(ws); ws = null; }
backoff = 1000;
ensureConnected();
},