feat: enhance WebSocket connection handling with reconnect logic and state management
All checks were successful
CI / test (push) Successful in 6s

This commit is contained in:
Space-Banane
2026-05-27 18:41:30 +02:00
parent 336ef97c49
commit 375c1073ec

View File

@@ -61,8 +61,10 @@ def monitoring_page_html() -> str:
token: localStorage.getItem("screenjob_token") || "",
jobs: [],
selectedJobId: null,
ws: null
ws: null,
wsReconnectTimer: null
};
const manuallyClosedSockets = new WeakSet();
tokenInput.value = state.token;
function authHeaders() {
@@ -119,15 +121,26 @@ def monitoring_page_html() -> str:
}
function pushEventLine(obj) {
if (!obj || !obj.job_id || !obj.event_type) return;
const line = document.createElement("div");
line.className = "border-b border-slate-800 pb-1";
line.textContent = `[${obj.ts}] ${obj.job_id} step=${obj.step} ${obj.event_type} ${JSON.stringify(obj.payload || {})}`;
const ts = obj.ts || "-";
const step = (obj.step ?? "-");
line.textContent = `[${ts}] ${obj.job_id} step=${step} ${obj.event_type} ${JSON.stringify(obj.payload || {})}`;
eventsEl.prepend(line);
while (eventsEl.childNodes.length > 400) {
eventsEl.removeChild(eventsEl.lastChild);
}
}
function scheduleWsReconnect() {
if (state.wsReconnectTimer || !state.token) return;
state.wsReconnectTimer = setTimeout(() => {
state.wsReconnectTimer = null;
connectWs();
}, 1200);
}
function updateLatestVisualFromEvent(ev) {
if (!ev || ev.event_type !== "visual_update") return;
if (!state.selectedJobId || ev.job_id !== state.selectedJobId) return;
@@ -164,16 +177,17 @@ def monitoring_page_html() -> str:
}
function connectWs() {
if (state.ws) {
try { state.ws.close(); } catch (_) {}
}
if (!state.token) return;
if (state.ws && (state.ws.readyState === WebSocket.OPEN || state.ws.readyState === WebSocket.CONNECTING)) {
return;
}
const scheme = location.protocol === "https:" ? "wss" : "ws";
const ws = new WebSocket(`${scheme}://${location.host}/ws?token=${encodeURIComponent(state.token)}`);
state.ws = ws;
ws.onmessage = async (event) => {
try {
const payload = JSON.parse(event.data);
if (!payload || payload.event_type === "connected") return;
pushEventLine(payload);
updateLatestVisualFromEvent(payload);
if (!state.selectedJobId || payload.job_id === state.selectedJobId) {
@@ -185,7 +199,14 @@ def monitoring_page_html() -> str:
console.error(err);
}
};
ws.onclose = () => setTimeout(connectWs, 1200);
ws.onclose = () => {
if (state.ws === ws) state.ws = null;
if (manuallyClosedSockets.has(ws)) {
manuallyClosedSockets.delete(ws);
return;
}
scheduleWsReconnect();
};
}
async function fullRefresh() {
@@ -197,6 +218,15 @@ def monitoring_page_html() -> str:
async function connect() {
state.token = tokenInput.value.trim();
localStorage.setItem("screenjob_token", state.token);
if (state.ws) {
manuallyClosedSockets.add(state.ws);
try { state.ws.close(); } catch (_) {}
state.ws = null;
}
if (state.wsReconnectTimer) {
clearTimeout(state.wsReconnectTimer);
state.wsReconnectTimer = null;
}
await fullRefresh();
connectWs();
}