Repository navigation
fix(web): evict the read cache by recency and hold plain request keys - #1604
Conversation
The read cache's 400-entry bound evicted by insertion order: a hit called Map.set on an existing key, which keeps its position. A hit or release now re-inserts the entry, and past the bound only the excess goes, idle-expired entries first, then the least recently read, in-flight reads last. Preload held superseding re-read keys with their generation suffix, which never match a cache entry, so their release did nothing. It now holds the plain request key. The page Model walk for live keys runs only when a step asks for new keys, not on every page message.
Maple review🟢 Confidence 10/10 · safe to merge Rewrites the read cache's bound to evict expired-then-least-recently-read entries, holds plain request keys in preload so releases reach the cache, and makes the page Model walk lazy. The eviction math and key handling check out; safe to merge.
Findings🔵 Note · F1 ·
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
🍁 Maple PR previewNote Preview resources were removed when this pull request closed. Final commit |
A load slow enough for the bound's worth of reads to land behind it kept its original slot on settle, so the next insert evicted the value it had just fetched. Settling now moves the entry to the recency end, like a hit.
|
Maple review F1 fixed in 9f6bb47: |
Maple review🟢 Confidence 10/10 · safe to merge Makes the web read cache evict by recency (expired first, in-flight last), moves a settled read to the recency end, and has preload hold and release the plain request key so its release actually matches a cache entry. Behaviour is pinned by new cache and preload tests; safe to merge.
Fixed since the last review
What was checked
|
|
Preview test on
Noticed, not from this PR: |
|
Traces from the preview test (Maple,
|
First step from the web fetching-layer audit: read cache hygiene.
What changed
data/read-cache.ts: the 400-entry bound claimed LRU but evicted by insertion order (a hit calledMap.seton an existing key, which keeps its position). A hit or release now re-inserts the entry. Past the bound only the excess goes, ranked idle-expired first, then least recently read, in-flight reads last. Expired entries below the bound stay on purpose: a page still holding one revives it on release.page/preload.ts: superseding re-reads put a\u0001Ngeneration on their key. Preload held and released those raw keys, which never match a cache entry, so the release was a no-op. It now holds the plain request key (baseKey).update.ts: the page Model walk that collects live keys used to run on every page message (hover, typing). It's now a thunk, called only when a step asks for new keys.invalidate(prefix)from the audit is left out: no write path reads through the cache yet, so it lands with the query builder instead.Verification
read-cache.test.tscases (LRU order, expired-first eviction, only the excess goes with a held entry revived on release). All three fail onmain's cache, and the last one also fails on a sweep-all version.preload.test.tscases: slot keys strip the generation, and a step with no new keys never calls the live-keys walk.vitest run src/data src/page/preload.test.ts src/update.test.ts: 45 passed.tsrs --noEmitclean, oxlint clean on the changed files.cappedswept every expired entry, which is fixed and covered by the third test.Need help on this PR? Tag
@codesmith-botwith what you need.Summary by CodeRabbit