refactor(#2815): held_transients -> running_transients

mara on !2910: "rename now, we will see if we can remove it later when
some of the users have been removed or work differently."

Nothing is held. The old name described a transient the DAG declared and
kept for its whole lifetime — precisely the thing this PR replaces — so
it outlived its own meaning the moment the derivation landed. The value
is recomputed from the running set on every call.

Kept as a function rather than inlined at its single call site, per the
above: removing it is a later step that depends on its users changing,
not something this PR should force.

Rename plus its two references (the call in `reconcile_transients` and
the module doc link). No behaviour change; the doc comment records what
the old name meant so the rename doesn't erase the reason for it.

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:
atlas 2026-08-01 16:39:38 +02:00
commit 17500a391d
2 changed files with 23 additions and 28 deletions

View file

@ -399,35 +399,30 @@ impl JobQueue {
.map(ToOwned::to_owned)
}
/// The `(agent, label)` pairs for the live transient-pill set — derived from
/// the nodes **actually running**, not from an intent a template declared at
/// submit time. A rebuild used to report `rebuilding` for its whole life:
/// through the prebuild, the stop, the swap, the tail and the reconcile.
/// `(agent, label, takes_container_down)` for the live transient-pill set,
/// recomputed from the nodes **actually running** — not from an intent a
/// template declared at submit time. (A rebuild used to report `rebuilding`
/// for its whole life: prebuild, stop, swap, tail and reconcile alike.)
///
/// A node lights a pill when it is `Running` **and declares the agent's
/// resource itself**. Declaring is the test, not targeting: `Prebuild` and
/// `MetaSync` name an agent but are lease-exempt on purpose — the container
/// keeps serving right through them — so they must not light one. It is also
/// not the *lease owner*: `resource_state()` answers "who holds the slot",
/// a different question from "what is running".
/// resource itself**. Declaring is the test, not targeting — `Prebuild` /
/// `MetaSync` name an agent but are lease-exempt on purpose, since the
/// container keeps serving through them. Nor is it the lease *owner*:
/// `resource_state()` answers "who holds the slot", a different question.
///
/// The label is the node's own wire tag ([`NodeKind::as_str`]) — the same
/// vocabulary [`NodeView::kind`] already ships, so a pill and a DAG node
/// name an operation identically and there is no second taxonomy to keep in
/// step.
/// `label` is the node's own wire tag ([`NodeKind::as_str`]), the vocabulary
/// [`NodeView::kind`] already ships, so a pill and a DAG node name an
/// operation identically. `takes_container_down` is the crash watcher's
/// input, carried rather than inferred from the label — a `Start` pill and a
/// `Stop` pill are both pills; only one means a vanished container is
/// expected.
///
/// Consequence, by design: `Start` / `Stop` / `PostSwap` run *inside* a
/// lease-holding ancestor and re-declare nothing, so they light no pill and
/// the agent reads idle for those windows. Closing that is the point of the
/// resources-where-constructed work, not of this function.
///
/// An agent's lease is cap-1, so at most one pair per agent.
/// The third element is [`NodeKind::takes_container_down`] — the crash
/// watcher's input, carried alongside the label rather than inferred from
/// it (a `Start` pill and a `Stop` pill are both pills; only one of them
/// means a vanished container is expected).
/// By design, `Start` / `Stop` / `PostSwap` run inside a lease-holding
/// ancestor and re-declare nothing, so they light no pill; closing that is
/// the resources-where-constructed work, not this function. An agent's lease
/// is cap-1, so at most one entry per agent.
#[must_use]
pub fn held_transients(&self) -> Vec<(String, String, bool)> {
pub fn running_transients(&self) -> Vec<(String, String, bool)> {
let inner = self.lock();
inner
.sched

View file

@ -5,7 +5,7 @@
//!
//! Owns the per-agent transient guard (dashboard pill + crash-watch
//! suppression) that the sync queue core can't hold itself. The guard set is
//! *reconciled* each loop from [`super::JobQueue::held_transients`], which
//! *reconciled* each loop from [`super::JobQueue::running_transients`], which
//! reports what is **running right now** under each held agent lease — so the
//! label tracks the DAG's progress (signal → swap → reconcile) instead of
//! repeating one intent the template declared before any of it started.
@ -171,9 +171,9 @@ fn reconcile_transients(
coord: &Arc<Coordinator>,
transients: &mut HashMap<String, (String, crate::coordinator::TransientGuard)>,
) {
let held = coord.job_queue.held_transients();
transients.retain(|agent, (label, _)| held.iter().any(|(a, l, _)| a == agent && l == label));
for (agent, label, takes_down) in held {
let running = coord.job_queue.running_transients();
transients.retain(|agent, (label, _)| running.iter().any(|(a, l, _)| a == agent && l == label));
for (agent, label, takes_down) in running {
transients.entry(agent.clone()).or_insert_with(|| {
let guard = coord.transient_guard(&agent, label.clone(), takes_down);
(label, guard)