v0.14.25
This commit is contained in:
@@ -131,17 +131,58 @@ async function handleWebSocketMessage(event) {
|
||||
} catch (_) { }
|
||||
}
|
||||
|
||||
const WEBSOCKET_RECONNECT_DELAY_MS = 3000;
|
||||
const WEBSOCKET_ERROR_DELAY_MS = 15000;
|
||||
|
||||
function clearWebSocketOutage() {
|
||||
app.wsOutageStartedAt = 0;
|
||||
clearTimeout(app.wsErrorTimer);
|
||||
app.wsErrorTimer = null;
|
||||
}
|
||||
|
||||
function markWebSocketOutage() {
|
||||
if (!app.wsOutageStartedAt) app.wsOutageStartedAt = Date.now();
|
||||
const elapsed = Date.now() - app.wsOutageStartedAt;
|
||||
if (elapsed >= WEBSOCKET_ERROR_DELAY_MS) {
|
||||
updateConnectionIndicator('connectionError');
|
||||
return;
|
||||
}
|
||||
updateConnectionIndicator('reconnecting');
|
||||
if (app.wsErrorTimer) return;
|
||||
app.wsErrorTimer = setTimeout(() => {
|
||||
app.wsErrorTimer = null;
|
||||
if (app.ws?.readyState === WebSocket.OPEN || !app.wsOutageStartedAt) return;
|
||||
updateConnectionIndicator('connectionError');
|
||||
}, WEBSOCKET_ERROR_DELAY_MS - elapsed);
|
||||
}
|
||||
|
||||
function connectWebSocket() {
|
||||
if (app.ws && [WebSocket.OPEN, WebSocket.CONNECTING].includes(app.ws.readyState)) return;
|
||||
clearTimeout(app.wsTimer);
|
||||
app.wsTimer = null;
|
||||
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const query = app.token ? `?token=${encodeURIComponent(app.token)}` : '';
|
||||
const ws = new WebSocket(`${protocol}//${location.host}${withBase('/ws')}${query}`); app.ws = ws;
|
||||
ws.onopen = () => updateConnectionIndicator('connected');
|
||||
ws.onclose = () => { app.controlPlanPushReady = false; updateConnectionIndicator('disconnected'); scheduleControlPlanLoad(0); app.wsTimer = setTimeout(connectWebSocket, 3000); };
|
||||
ws.onerror = () => updateConnectionIndicator('connectionError');
|
||||
ws.onopen = () => {
|
||||
if (app.ws !== ws) return;
|
||||
clearWebSocketOutage();
|
||||
updateConnectionIndicator('connected');
|
||||
};
|
||||
ws.onclose = () => {
|
||||
if (app.ws !== ws) return;
|
||||
app.controlPlanPushReady = false;
|
||||
markWebSocketOutage();
|
||||
scheduleControlPlanLoad(0);
|
||||
app.wsTimer = setTimeout(connectWebSocket, WEBSOCKET_RECONNECT_DELAY_MS);
|
||||
};
|
||||
// Browser WebSocket errors are transport-level signals and are normally followed by `close`.
|
||||
// Let `close` drive reconnect state so a transient error does not look like an application failure.
|
||||
ws.onerror = () => {
|
||||
if (app.ws === ws) console.warn('WebSocket transport error; waiting for close/reconnect');
|
||||
};
|
||||
let messageQueue = Promise.resolve();
|
||||
ws.onmessage = event => {
|
||||
if (app.ws !== ws) return;
|
||||
messageQueue = messageQueue.then(() => handleWebSocketMessage(event)).catch(() => { });
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user