refactor(#2815): the scheduler publishes pill edges, it doesn't own pills
mara on !2910: "transient guard as well - should be removable now?" — for the queue path, yes. `set_transient`'s own doc explained why the RAII guard existed: a cancelled future must not leak an imperatively-set transient and pin the dashboard on "rebuilding…" forever. That cannot happen to a derived set. `running_transients()` is recomputed from the graph every loop, so a node that stops running stops appearing — there is nothing to own and nothing to leak. So the scheduler no longer holds a guard per pill. It keeps the previous derived value and publishes the transitions, which is the one thing a derived read cannot express: the dashboard wants `TransientSet` / `TransientCleared` edges, and the crash watcher wants the *moment* a pill cleared, since its grace window is what stops an operator stop from reading as a crash. That also retires a hazard rather than restating it. The old code carried a warning that stale guards had to be dropped before new ones were created, because `TransientGuard::drop` clears by agent with no notion of which label it was clearing — so a same-agent label change could clear the pill it had just set. With no guards there is no ordering to get wrong; clears are emitted before sets so a relabel reads as clear-then-set rather than two overlapping pills. `set_transient` / `clear_transient` become `pub(crate)`. The guard stays for destroy and migration, which have no node behind them and where the cancellation concern is real. Checked with clippy (`--all-targets -D warnings`), `cargo test -p hive-c0re -p hive-jobq` (322 + 41 passed) and `nix fmt`.
This commit is contained in:
parent
17500a391d
commit
56202065d5
2 changed files with 57 additions and 36 deletions
|
|
@ -1077,13 +1077,17 @@ impl Coordinator {
|
|||
|
||||
/// Mark an agent as in-progress (only one state per agent for now).
|
||||
///
|
||||
/// Private on purpose: the RAII [`TransientGuard`] (via
|
||||
/// [`Coordinator::transient_guard`]) is the only door, so the paired
|
||||
/// `clear_transient` always runs on drop even if the surrounding future
|
||||
/// is cancelled (HTTP request aborted, runtime shutdown mid-rebuild,
|
||||
/// panic). A bare set with no guaranteed clear would leak the transient
|
||||
/// and leave the dashboard stuck in "rebuilding…" forever.
|
||||
fn set_transient(&self, name: &str, label: String, deliberate_stop: bool) {
|
||||
/// Two callers, for two different reasons:
|
||||
/// - **Work with a queue node behind it** — the job-queue scheduler, which
|
||||
/// publishes the edges of a *derived* set
|
||||
/// ([`crate::job_queue::JobQueue::running_transients`]). It needs no guard:
|
||||
/// nothing is owned, and a node that stops running stops appearing.
|
||||
/// - **Work with no node** (destroy, migration) — via the RAII
|
||||
/// [`TransientGuard`], so the paired `clear_transient` still runs if the
|
||||
/// surrounding future is cancelled (HTTP request aborted, shutdown
|
||||
/// mid-rebuild, panic). There a bare set really would leak the transient
|
||||
/// and pin the dashboard on "rebuilding…" forever.
|
||||
pub(crate) fn set_transient(&self, name: &str, label: String, deliberate_stop: bool) {
|
||||
self.transient.lock().unwrap().insert(
|
||||
name.to_owned(),
|
||||
TransientState {
|
||||
|
|
@ -1108,10 +1112,11 @@ impl Coordinator {
|
|||
});
|
||||
}
|
||||
|
||||
/// Clear an agent's transient state. Private: only reachable through
|
||||
/// [`TransientGuard`]'s `Drop`, which guarantees it runs (see
|
||||
/// [`Coordinator::set_transient`]).
|
||||
fn clear_transient(&self, name: &str) {
|
||||
/// Clear an agent's transient state. Reached either from
|
||||
/// [`TransientGuard`]'s `Drop` (the no-node callers) or from the scheduler
|
||||
/// when a derived pill stops being current — see
|
||||
/// [`Coordinator::set_transient`].
|
||||
pub(crate) fn clear_transient(&self, name: &str) {
|
||||
let removed = self.transient.lock().unwrap().remove(name);
|
||||
if let Some(state) = removed {
|
||||
// Stamp the tombstone so the crash watcher can still see
|
||||
|
|
|
|||
Loading…
Reference in a new issue