fix: stop aggressive API polling and SSE reconnect when auth lost
When unauthenticated (TOTP gate active), the dashboard was polling /api/v1/services/status every few seconds and reconnecting SSE every 2-8s indefinitely. Now: 401/403 sets _dcAuthLost flag to skip the polling interval, and SSE stops after 5 consecutive failures.
This commit is contained in:
Vendored
+32
-32
File diff suppressed because one or more lines are too long
Vendored
+2
-2
File diff suppressed because one or more lines are too long
@@ -401,9 +401,15 @@
|
|||||||
refreshInFlight = (async () => {
|
refreshInFlight = (async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/v1/services/status', { cache: 'no-store' });
|
const response = await fetch('/api/v1/services/status', { cache: 'no-store' });
|
||||||
|
if (response.status === 401 || response.status === 403) {
|
||||||
|
// Auth lost — stop the polling loop from hammering every few seconds
|
||||||
|
window._dcAuthLost = true;
|
||||||
|
throw new Error(`Authentication required (${response.status})`);
|
||||||
|
}
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Status refresh failed (${response.status})`);
|
throw new Error(`Status refresh failed (${response.status})`);
|
||||||
}
|
}
|
||||||
|
window._dcAuthLost = false; // auth working again
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
applyBatchResults(data.statuses || {});
|
applyBatchResults(data.statuses || {});
|
||||||
updateStamp('last check', data.checkedAt || new Date());
|
updateStamp('last check', data.checkedAt || new Date());
|
||||||
|
|||||||
@@ -63,7 +63,12 @@
|
|||||||
window.buildGrid();
|
window.buildGrid();
|
||||||
animateTopCards();
|
animateTopCards();
|
||||||
window.refreshAll();
|
window.refreshAll();
|
||||||
setInterval(window.refreshAll, DC.POLL.DASHBOARD);
|
setInterval(() => {
|
||||||
|
// Stop polling if the session has been invalidated (e.g. TOTP gate
|
||||||
|
// now active, or user logged out). Avoids relentless 401/403 noise.
|
||||||
|
if (window._dcAuthLost) return;
|
||||||
|
window.refreshAll();
|
||||||
|
}, DC.POLL.DASHBOARD);
|
||||||
if (typeof window.refreshCredsButtons === 'function') window.refreshCredsButtons();
|
if (typeof window.refreshCredsButtons === 'function') window.refreshCredsButtons();
|
||||||
if (typeof window.refreshMonitoringWidgets === 'function') window.refreshMonitoringWidgets();
|
if (typeof window.refreshMonitoringWidgets === 'function') window.refreshMonitoringWidgets();
|
||||||
// Update auth card (may have already been updated by the auto-load IIFE but ensure it's correct)
|
// Update auth card (may have already been updated by the auto-load IIFE but ensure it's correct)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
es.addEventListener('connected', () => {
|
es.addEventListener('connected', () => {
|
||||||
reconnectDelay = 1000; // reset backoff
|
reconnectDelay = 1000; // reset backoff
|
||||||
|
_sseFailCount = 0; // reset failure counter
|
||||||
debug('[SSE] Connected to event stream');
|
debug('[SSE] Connected to event stream');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -101,12 +102,21 @@
|
|||||||
// Reconnect on error
|
// Reconnect on error
|
||||||
es.onerror = () => {
|
es.onerror = () => {
|
||||||
es.close();
|
es.close();
|
||||||
|
// Stop reconnecting entirely after multiple consecutive failures
|
||||||
|
// (likely auth-gate / session expired — no point hammering forever)
|
||||||
|
_sseFailCount = (_sseFailCount || 0) + 1;
|
||||||
|
if (_sseFailCount > 5) {
|
||||||
|
console.warn('[SSE] Max reconnect attempts reached — stopping (auth gate active or server unreachable)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
console.warn(`[SSE] Disconnected, reconnecting in ${reconnectDelay / 1000}s...`);
|
console.warn(`[SSE] Disconnected, reconnecting in ${reconnectDelay / 1000}s...`);
|
||||||
setTimeout(connect, reconnectDelay);
|
setTimeout(connect, reconnectDelay);
|
||||||
reconnectDelay = Math.min(reconnectDelay * 2, MAX_RECONNECT);
|
reconnectDelay = Math.min(reconnectDelay * 2, MAX_RECONNECT);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let _sseFailCount = 0;
|
||||||
|
|
||||||
// Start on page load
|
// Start on page load
|
||||||
connect();
|
connect();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user