fc8a40cfc6
Review fixes on top of cb2b104:
- Delete the write-only in-memory refuseUntil map and setRefusalBackoff now
that status.go is gone: the pass gate reads the durable stamp, so the map
was half-deleted dead state (spec review C-1).
- An outcome-query failure no longer blanks the Lane table into the false
'no data yet': rows render with 'none observed' chips instead (I-1).
- due-query and eligible-count skips get their own sentences instead of the
merged 'check failed' (I-2).
- ADR-0012 constrain wording corrected and trailing newline added (M-1)
44 lines
2.1 KiB
Markdown
44 lines
2.1 KiB
Markdown
# ADR-0012: Persisted lane state
|
|
|
|
Date: 2026-08-21
|
|
Status: accepted
|
|
|
|
Supersedes the in-memory lane snapshot carried by `latest`'s `LaneState`/`Status`
|
|
and the `web.LaneReporter` seam (ADR-0010 wrote the durable rows this page now
|
|
reads).
|
|
|
|
## Decision
|
|
|
|
The admin Lanes page stops reading the poller's in-memory Lane state and
|
|
becomes a read of `poll_passes`/`poll_lanes` in Postgres. There is no
|
|
`LaneReporter` interface: `web/admin_lanes.go` walks `store.LatestLanePasses()`
|
|
into one row per Site and adds the window's outcome sums from
|
|
`store.LanePassOutcomes()`. The `latest` package's `LaneState`/`Status` snapshot
|
|
and its `web.LaneReporter` seam are deleted.
|
|
|
|
The browser is a deployment configuration fact plus a reachability derived
|
|
from the pass log: `BROWSER_WS_URL` set means "configured", and the browser is
|
|
"reachable" unless a recent browser-Site pass inside `latest.RefuseBackoff` is
|
|
a sidecar loss, a missing fetcher, or an interrupted read. A skip reason is
|
|
the whole difference between a Lane resting and a Lane stuck: a skipped pass
|
|
prints its sentence, and only an empty skip with Series due and none read
|
|
draws the true-stall fault. Sleep skips never count toward `Attention`.
|
|
|
|
## Why
|
|
|
|
The old page lived on a poller snapshot. Because that state was in memory, a
|
|
deploy erased it: the page read zeroes until a fresh pass ran, and browser
|
|
reachability came through a reporter interface only a live poller could
|
|
serve. Making the page answer from the database means a restart is complete
|
|
the instant the store is up, the browser fact survives a poller restart, and
|
|
a Lane that has not yet gathered figures shows a placeholder rather than a
|
|
confident zero.
|
|
|
|
## Constraints
|
|
|
|
The poller still owns the writes: each pass exit records one row (ADR-0010),
|
|
and a pass that returns before gathering figures carries the previous pass's
|
|
numbers forward instead of recording zeroes. A skip is a stable wire string;
|
|
`asleep` never counts toward `Attention`. When polling is switched off
|
|
(`LATEST_CHAPTER_POLL_ENABLED` unset) the page must say so, and the browser
|
|
statusline appears only when polling is switched on. |