Notification bell: pause polling when tab hidden, backoff on failure (#59)
setInterval(loadNotifications, 60000) ran unconditionally regardless of tab visibility, and failures retried at the same fixed 60s cadence forever. Now skips polling while document.hidden, resumes immediately via visibilitychange when the tab regains focus, and backs off exponentially (capped at 5 min) on repeated fetch failures, resetting to the normal 60s cadence on the next success. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MGDKHiU5RJdo3dqQUDow3X
This commit is contained in:
+30
-4
@@ -235,11 +235,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadNotifications() {
|
function loadNotifications() {
|
||||||
fetch('/api/notifications.php', { credentials: 'same-origin' })
|
return fetch('/api/notifications.php', { credentials: 'same-origin' })
|
||||||
.then(function(r) { return r.json(); })
|
.then(function(r) { return r.json(); })
|
||||||
.then(renderNotifications)
|
.then(function(data) { renderNotifications(data); return true; })
|
||||||
.catch(function() {
|
.catch(function() {
|
||||||
list.innerHTML = '<div style="padding:0.75rem;font-size:0.75rem;color:var(--text-muted);text-align:center">Could not load</div>';
|
list.innerHTML = '<div style="padding:0.75rem;font-size:0.75rem;color:var(--text-muted);text-align:center">Could not load</div>';
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,9 +262,34 @@
|
|||||||
document.addEventListener('click', function(e) { if (_open && wrapEl && !wrapEl.contains(e.target)) closePanel(); });
|
document.addEventListener('click', function(e) { if (_open && wrapEl && !wrapEl.contains(e.target)) closePanel(); });
|
||||||
document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && _open) closePanel(); });
|
document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && _open) closePanel(); });
|
||||||
|
|
||||||
// Initial badge count + poll every 60s
|
// Poll every 60s while the tab is visible, backing off (up to 5 min) on
|
||||||
|
// repeated failures, and resuming immediately when the tab regains focus.
|
||||||
|
var POLL_INTERVAL = 60000;
|
||||||
|
var MAX_POLL_INTERVAL = 300000;
|
||||||
|
var _pollTimer = null;
|
||||||
|
var _failCount = 0;
|
||||||
|
|
||||||
|
function scheduleNextPoll(delay) {
|
||||||
|
clearTimeout(_pollTimer);
|
||||||
|
_pollTimer = setTimeout(pollNotifications, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pollNotifications() {
|
||||||
|
if (document.hidden) return;
|
||||||
|
loadNotifications().then(function(ok) {
|
||||||
|
_failCount = ok ? 0 : _failCount + 1;
|
||||||
|
var delay = ok ? POLL_INTERVAL : Math.min(POLL_INTERVAL * Math.pow(2, _failCount), MAX_POLL_INTERVAL);
|
||||||
|
scheduleNextPoll(delay);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('visibilitychange', function() {
|
||||||
|
if (!document.hidden) pollNotifications();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initial badge count, then start the poll cycle
|
||||||
loadNotifications();
|
loadNotifications();
|
||||||
setInterval(loadNotifications, 60000);
|
scheduleNextPoll(POLL_INTERVAL);
|
||||||
})();
|
})();
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user