44 lines
1.7 KiB
TypeScript
44 lines
1.7 KiB
TypeScript
/** Coalesce pushes, serialize refreshes, and recover missed events after reconnect or tab activation. */
|
|
export function betaUpdates(load: () => Promise<unknown>, betaId?: () => number): () => void {
|
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
let stopped = false,
|
|
running = false,
|
|
pending = false;
|
|
const schedule = () => {
|
|
pending = true;
|
|
if (stopped || running || timer || document.hidden) return;
|
|
timer = setTimeout(async () => {
|
|
timer = undefined;
|
|
if (stopped || document.hidden) return;
|
|
running = true;
|
|
pending = false;
|
|
try {
|
|
await load();
|
|
} catch {
|
|
/* The page owns its error state; later events can retry. */
|
|
} finally {
|
|
running = false;
|
|
if (pending) schedule();
|
|
}
|
|
}, 200);
|
|
};
|
|
const changed = (event: Event) => {
|
|
if (!betaId || (event as CustomEvent).detail?.betaId === betaId()) schedule();
|
|
};
|
|
const visible = () => {
|
|
if (!document.hidden) schedule();
|
|
};
|
|
window.addEventListener('ec:beta-changed', changed);
|
|
window.addEventListener('ec:pipeline-connected', schedule);
|
|
window.addEventListener('ec:fleet-changed', schedule);
|
|
document.addEventListener('visibilitychange', visible);
|
|
return () => {
|
|
stopped = true;
|
|
clearTimeout(timer);
|
|
window.removeEventListener('ec:beta-changed', changed);
|
|
window.removeEventListener('ec:pipeline-connected', schedule);
|
|
window.removeEventListener('ec:fleet-changed', schedule);
|
|
document.removeEventListener('visibilitychange', visible);
|
|
};
|
|
}
|