// The stream half of the revision discipline; the READ half is `freshest()` in `queries.ts`. // // The split is deliberate. A frame has nothing to compare itself against, so its high-water mark // has to be kept here. A read does — the query cache, which the stream patches — and keeping a // second copy of it here was how progress rolled backwards: the copy went stale the moment a frame // landed, and a read was compared against the copy instead of against what was on screen. // One entry per book being watched, holding a number. Dropped when the subscription closes. const applied = new Map(); /** * Whether a stream frame carries anything new. Equal revisions pass: one transaction is one * revision but SEVERAL frames, and rejecting equality would drop the siblings of the frame already * applied — the same reason catch-up reads `>=` and not `>`. */ export function acceptFrame(scope: string, revision: number): boolean { const last = applied.get(scope); if (last !== undefined && revision < last) return false; applied.set(scope, revision); return true; } /** Drops the mark for a scope — after a resync there is nothing to compare against. */ export function forget(scope: string): void { applied.delete(scope); } /** Test seam: the registry is module state, and a leftover revision would leak between tests. */ export function forgetAll(): void { applied.clear(); }