feat(events): stream Redis invalidations over SSE

This commit is contained in:
2026-08-28 20:03:11 +00:00 Unverified
parent b59a038351
commit 455e4240ac
16 changed files with 453 additions and 1 deletions
+58
View File
@@ -0,0 +1,58 @@
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;
},
};
}