feat(events): stream Redis invalidations over SSE
This commit is contained in:
@@ -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;
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user