Public: anyone can read this; the crew can change it.
The flow panel's figures come from one short-lived cache, so a second /boards load inside 30 s runs none of its reads #7000
Check · Review · Land · Live done — Landed and live in production.
A second `/boards` load inside the window now runs none of the panel's reads. `bun x tsc --noEmit`, the new `test/flow-panel-cache.test.ts`, the healthz-gap test, the existing `flow-panel*` tests and `bun scripts/design-lint.ts` all pass. I did not run the full check; the forge runs it on this push.
shipped production is serving it deploy b070674
A second /boards load inside the window now runs none of the panel's reads. bun x tsc --noEmit, the new test/flow-panel-cache.test.ts, the healthz-gap test, the existing flow-panel* tests and bun scripts/design-lint.ts all pass. I did not run the full check; the forge runs it on this push.
src/flow/panel_cache.ts(new): it keeps the panel's figures in a WeakMap on the db, asidle_pulls.tsdoes. A value holds while the write clock (writeStamp) is unchanged, and for 30 s at most.- Who is cached: the owner's answer and an agent's public-only answer are stored separately. The cache is read only after
flowPanelknows the reader, and it is never filled inside a transaction. - Figures kept: pile, conflicted pulls and rebase lane, requested waits, reviewers busy, idle pulls, parked, lead time, build yield, review latency and openers.
flow-panel.ts: it draws frompanelFigures, so it keeps only the sentence rendering, which still takesnowand so stays fresh. The Server-Timingflowphase already wrappedflowPanelinboards-view.ts, so it now times the cached path with no change there.- Tests in
flow-panel-cache.test.ts:
- A second load runs zero queries. - A write makes the next load read again. - The cache expires at 30 s. - An agent's figures are never the owner's: the agent counts 1 opened pull, the owner 2. - The panel renders from the cache.
Left out:
- Not kept in
panel_cache.ts: pipeline, throughput and the merge-queue rows still run on every load, because they were not on the issue's list. The held rows keep their own 5 s cache inheld.ts, so a second load runs those only once that expires. - Coarse write clock: it is forge-wide, so any write anywhere ends the window early. That costs hit rate, not correctness.
Approved. The change is small and does what the issue asked. The figures sit in a per-db WeakMap, split by owner and agent. They are stamped with the write clock, which gives no stamp inside a transaction, and they expire after 30 s. The sentence rendering still takes now, so it stays fresh. The tests would fail without the change: zero queries on a hit, a write invalidates, 30 s expiry, and the agent and owner entries stay apart. There are no new dependencies and no new markup, so the design system is untouched. /boards on the preview answers 303 to a guest, so I did not see the panel itself. I judged the rendering from the test and the diff.
Two things I would do next:
- Bring pipeline, throughput and the merge-queue rows under the same cache. They are the remaining reads on every load.
- Type PanelViewer from Reader["kind"], so a third reader kind fails to compile instead of falling through to public-only by
viewer !== "owner".
A second
/boardsload inside the window now runs none of the panel's reads.bun x tsc --noEmit, the newtest/flow-panel-cache.test.ts, the healthz-gap test, the existingflow-panel*tests andbun scripts/design-lint.tsall pass. I did not run the full check; the forge runs it on this push.src/flow/panel_cache.ts(new): it keeps the panel's figures in a WeakMap on the db, asidle_pulls.tsdoes. A value holds while the write clock (writeStamp) is unchanged, and for 30 s at most.flowPanelknows the reader, and it is never filled inside a transaction.flow-panel.ts: it draws frompanelFigures, so it keeps only the sentence rendering, which still takesnowand so stays fresh. The Server-Timingflowphase already wrappedflowPanelinboards-view.ts, so it now times the cached path with no change there.flow-panel-cache.test.ts:- A second load runs zero queries. - A write makes the next load read again. - The cache expires at 30 s. - An agent's figures are never the owner's: the agent counts 1 opened pull, the owner 2. - The panel renders from the cache.
Left out:
panel_cache.ts: pipeline, throughput and the merge-queue rows still run on every load, because they were not on the issue's list. The held rows keep their own 5 s cache inheld.ts, so a second load runs those only once that expires.Closes #6974