Bounded background write queue for the L2 (OPFS) tier.
The OPFS write (OPFSStore.set → createWritable/write/close, an atomic
temp-file swap per chunk) costs tens of ms and — measured on a true-cold
timelapse load — dominates the per-timepoint fetch critical path (~6× the
network fetch). OPFSStore.set already serializes writes per key, but has
no global cross-key cap, so firing every network miss's write inline (awaited)
blocks decode on disk, and firing them all un-awaited stampedes the single
OPFS backend (each write balloons under contention) and piles up unbounded.
This queue moves the write off the fetch critical path while keeping it
bounded: the caller enqueue()s and returns immediately; the queue drains
tasks at a fixed concurrency, coalesces repeat writes of the same key
(keeping the latest), and past maxDepth or maxBytes drops the ARRIVAL —
the entry that just overflowed — not the oldest pending one (L2 is a
best-effort persistence tier — L1 still serves the current session and the
next session simply re-fetches a dropped chunk).
Dropping the arrival rather than the oldest matters for what the next session
finds on disk. pump() takes from the same oldest end the drop loop used to
evict from, so drop-oldest kept discarding the entry the pump was about to
run and left a scattered remnant — chunks from all over the store, of which
no contiguous region is complete. Dropping the arrival lets the oldest end
drain in enqueue order, so what lands on disk is CONTIGUOUS RUNS from that
end (one prefix only while nothing drains; with the pump running, a run per
burst) — which is what a warm revisit can actually serve from. The tradeoff
is locality, not drop count: uniform-size writes drop equally under either
policy, while mixed sizes can favour either one. A large arrival no longer
displaces several small pending writes, but a large pending write can now
hold off several smaller arrivals.
PRIORITY. Each write is demand (a caller actually asked for the chunk) or
speculative (only the prefetcher wanted it). Under overflow a speculative
write is always the one to go, never a demand one:
a DEMAND arrival evicts the OLDEST pending speculative write(s) to make
room, and is itself dropped only when demand writes alone fill the queue;
a SPECULATIVE arrival for a new key is dropped (the drop-the-arrival rule
above, which keeps the oldest end contiguous);
a replacement for a key already pending (coalescing: the newer write wins)
prefers evicting OTHER speculative writes; when none can make room,
the replacement is dropped along with the task it replaced.
Every discarded write is counted in dropped (and in droppedSpeculative
when it was speculative) and in opfs.writesDropped — none is silent. A
replacement that fits after coalescing is not a drop: the latest bytes land.
Correctness is the caller's (MultiLevelCachingStore) responsibility: the
enqueued task must re-check staleness (disposed / dataAbort / epoch) at drain
time, because clear/dispose can now interleave between enqueue and drain.
Bounded background write queue for the L2 (OPFS) tier.
The OPFS write (
OPFSStore.set→createWritable/write/close, an atomic temp-file swap per chunk) costs tens of ms and — measured on a true-cold timelapse load — dominates the per-timepoint fetch critical path (~6× the network fetch).OPFSStore.setalready serializes writes per key, but has no global cross-key cap, so firing every network miss's write inline (awaited) blocks decode on disk, and firing them all un-awaited stampedes the single OPFS backend (each write balloons under contention) and piles up unbounded.This queue moves the write off the fetch critical path while keeping it bounded: the caller
enqueue()s and returns immediately; the queue drains tasks at a fixedconcurrency, coalesces repeat writes of the same key (keeping the latest), and pastmaxDepthormaxBytesdrops the ARRIVAL — the entry that just overflowed — not the oldest pending one (L2 is a best-effort persistence tier — L1 still serves the current session and the next session simply re-fetches a dropped chunk).Dropping the arrival rather than the oldest matters for what the next session finds on disk.
pump()takes from the same oldest end the drop loop used to evict from, so drop-oldest kept discarding the entry the pump was about to run and left a scattered remnant — chunks from all over the store, of which no contiguous region is complete. Dropping the arrival lets the oldest end drain in enqueue order, so what lands on disk is CONTIGUOUS RUNS from that end (one prefix only while nothing drains; with the pump running, a run per burst) — which is what a warm revisit can actually serve from. The tradeoff is locality, not drop count: uniform-size writes drop equally under either policy, while mixed sizes can favour either one. A large arrival no longer displaces several small pending writes, but a large pending write can now hold off several smaller arrivals.PRIORITY. Each write is
demand(a caller actually asked for the chunk) orspeculative(only the prefetcher wanted it). Under overflow a speculative write is always the one to go, never a demand one:dropped(and indroppedSpeculativewhen it was speculative) and inopfs.writesDropped— none is silent. A replacement that fits after coalescing is not a drop: the latest bytes land.Correctness is the caller's (MultiLevelCachingStore) responsibility: the enqueued task must re-check staleness (disposed / dataAbort / epoch) at drain time, because clear/dispose can now interleave between enqueue and drain.