@@ -398,14 +398,13 @@ function generateDashboardHTML(servicesWithStatus, refreshInterval = 5000) {
398398 wsConnection.onclose = function() {
399399 console.log('WebSocket disconnected');
400400 wsConnection = null;
401- isStreamingLogs = false;
402- updateStreamButton();
401+ scheduleReconnect();
403402 };
404403
405404 wsConnection.onerror = function(error) {
406405 console.error('WebSocket error:', error);
407- isStreamingLogs = false;
408- updateStreamButton ();
406+ // Attempt reconnect after error
407+ scheduleReconnect ();
409408 };
410409
411410 return wsConnection;
@@ -535,6 +534,27 @@ function generateDashboardHTML(servicesWithStatus, refreshInterval = 5000) {
535534 timeout = setTimeout(later, wait);
536535 };
537536 }
537+
538+ // --- Reconnection logic ---
539+ let reconnectAttempts = 0;
540+ const MAX_RECONNECT_DELAY = 30000; // 30s cap
541+ function scheduleReconnect() {
542+ // Don't reconnect if page is unloading
543+ if (document.visibilityState === 'unloading') return;
544+ reconnectAttempts++;
545+ const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), MAX_RECONNECT_DELAY);
546+ console.log('Scheduling WebSocket reconnect in', delay, 'ms');
547+ setTimeout(() => {
548+ initWebSocket();
549+ // restart stream with current filter
550+ const service = (currentLogsFilter.service || '');
551+ if (wsConnection && wsConnection.readyState === WebSocket.OPEN) {
552+ wsConnection.send(JSON.stringify({ type: 'start_log_stream', service: service || null }));
553+ } else if (wsConnection) {
554+ wsConnection.onopen = () => wsConnection.send(JSON.stringify({ type: 'start_log_stream', service: service || null }));
555+ }
556+ }, delay);
557+ }
538558 </script>
539559</head>
540560<body>
0 commit comments