Files
pulse/internal/actionlifecycle
rcourtman b329730e6b Keep a remediation lock readable on an ID a succession retired
A rebuild applies canonical-ID successions to the store, which moves the
predecessor's operator row to the successor, before it publishes the
registry generation that lists the successor. For the length of the
rebuild the previous generation keeps serving the old ID, and the planner,
the Patrol broker and both dispatch gates read the row of that ID. The row
had gone, so a lock the operator set did not refuse an action planned or
dispatched against it. Every kind of succession reaches this window:
pin-driven, Proxmox guest eras, and the host and Docker reporter eras.

GetResourceOperatorState now follows the recorded successions when an ID
holds no row, in both stores, through one walker. It answers as the ID the
chain ends on would, with that row's remediation block alone, so a lock
the operator lifted on the successor stays lifted, a chain that loops
ends, and nothing is written. The SQLite walk is one transaction, because
a succession that commits between two of its statements can move the lock
onto an ID the walk has already passed.

Delaying the move was rejected: later steps of the same rebuild read the
store, and plans already issued against the old ID would not be
protected. Seven tests that used a missing read to prove a row had moved
now read the rows directly. An operator edit to the retired ID inside the
window still does not reach the successor; the contract names it as a
limit.
2026-10-10 14:47:45 +01:00
..