Files
buzz-sheet/lib/events/refresh.ts
T

59 lines
1.3 KiB
TypeScript

import type { InvalidationEvent } from "./invalidation";
export interface RefreshScheduler {
connected(): void;
notified(event: InvalidationEvent): void;
dispose(): void;
}
export interface RefreshSchedulerOptions {
delayMs?: number;
duplicateWindowMs?: number;
now?: () => number;
}
export function createRefreshScheduler(
refresh: () => void,
options: RefreshSchedulerOptions = {},
): RefreshScheduler {
const delayMs = options.delayMs ?? 75;
const duplicateWindowMs = options.duplicateWindowMs ?? 2_000;
const now = options.now ?? Date.now;
let pending: ReturnType<typeof setTimeout> | undefined;
let lastEventKey: string | undefined;
let lastEventAt = 0;
const schedule = (event?: InvalidationEvent) => {
if (event) {
const key = `${event.type}:${event.id}:${event.version}`;
const timestamp = now();
if (
key === lastEventKey &&
timestamp - lastEventAt < duplicateWindowMs
) {
return;
}
lastEventKey = key;
lastEventAt = timestamp;
}
if (pending) return;
pending = setTimeout(() => {
pending = undefined;
refresh();
}, delayMs);
};
return {
connected() {
schedule();
},
notified(event) {
schedule(event);
},
dispose() {
if (pending) clearTimeout(pending);
pending = undefined;
},
};
}