Forced Poll: ask for one Series to be checked now #146
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent
Spec #134.
What to build
If one Series' Latest Chapter looks stuck, the owner currently waits for its turn in the Lane's hour. This ticket gives them Check now -- a control that writes a row the poller notices on its next pass, and never commands the poller. It survives a restart because it is a fact about the Series rather than about the running process, and the whole surface stays testable with no poller running at all.
One column already exists from the read-model ticket: a request stamp in unix ms, zero meaning never asked. Writing it again re-stamps the request time; the write is idempotent. Pending is derived, never stored: the request stamp is newer than the check stamp. It clears itself with no second write and no sweeper, because the check stamp is written before the fetch -- so the first attempt ends the pending state whatever the attempt returns. That stamp-before-fetch order is load-bearing; changing it silently makes forced requests sticky. No expiry: a request the Lane never reaches keeps ageing in the UI rather than vanishing, so an old pending marker is itself the evidence that a Lane is stuck. The control tells the owner how long ago they asked and gives no estimate, because the page does not know when a sleeping browser will wake.
The due query gains the flag in three places and forces the row to the front of the queue. A Forced Poll overrides the rest cutoff, the Sighting-deferral clause and the finished-only bucket. It never overrides an empty series URL (nothing to fetch), the Bookmarks join (a Series no Reader holds has no consumer for the result), the Lane's refusal backoff (hand-forcing a request at a Site that is actively refusing is the one move that makes it worse), the sidecar-down skip, or the Lane's gap. One pass-level gate it does open: the browser wake thresholds. A forced Series wakes a sleeping Chrome -- those thresholds exist to stop the machine waking itself for one unattended check, and a human asking is not that. If the home machine is off, nothing happens and the request ages visibly.
Two notes for whoever implements the query. The finished-status clause in the current due query is today's Lifecycle test and is deleted by a later spec in this series; implement it as it stands, that spec replaces it rather than amending it. And rejected: zeroing the check stamp as the force signal -- it corrupts the never-checked and stale counts the landing page exists to show, and makes a pending marker impossible.
The control is unconfirmed -- it takes nothing away -- and answers with the freshly rendered row, so the figures describe the state after the press. The ageing pending marker renders once, on the title line flush right above the actions; under the action it added a second line to every row. The control is hidden on a Series with no page to fetch and on one no Reader holds, so the owner is never offered a button that can never do anything. It appears on both the Series list row and the Series detail page.
Write the ADR for the through-the-database command seam and its queue-jump rules with this implementation.
Acceptance criteria
go test ./...greenBlocked by
Merged into
spec-134(branchticket/146-forced-poll, commitsfe2cd12,5b7adf5).Check now lands on both the Series list row and the detail page, writing
series.force_poll_atthroughPOST /admin/series/{key}/polland never commanding the poller. Pending is derived (force_poll_at > latest_checked_at), self-clears on the check stamp with no second write — including when the attempt fails — and never expires. The due query gained the flag in its three places plus the queue jump, and a forced Series opens the browser wake thresholds while still respecting the empty-URL filter, the Bookmarks join and the refusal backoff. ADR-0013 lands with it. No migration: 0014 already added the column.The stamp-before-fetch ordering has its own test that fails if the order is swapped, as the acceptance criteria require.
Security invariants preserved and stated: parameterised SQL only, 64 KiB
MaxBytesReaderbeforeParseForm, owner gate in the route list rather than inside the handler,html/templateoutput only, generic client errors with detail logged.Review: both axes clean, one Minor fixed per axis.
Known shortcut,
ponytail:-commented in-tree: twoSeriesPagescans per press rather than a keyed read, with the upgrade path named.go test ./...green on the merged base.