jobq: a transient is any running node naming the agent
Per mara on #2822: status is the only test. The agent comes off the node's own payload rather than a declared Resource::Agent edge, so the lease-exempt kinds (Prebuild, MetaSync) that name an agent without holding its lease now light a pill — they are work on that agent. Dropping that test breaks the one-pill-per-agent invariant, since lease-exemption is exactly what lets one DAG build for an agent while another holds its lease. Everything keyed by agent alone had to follow: - reconcile_transients keys (agent, label) via TransientSeen, so a second pill cannot evict the first — and cannot lose its takes_container_down, which the crash watcher reads at clear time. - transient_snapshot returns a Vec per agent for the same reason. The collapse was silent: a Prebuild could evict a StopForUpdate and its deliberate_stop, making an intentional stop report as a crash. - crash_watch asks whether ANY running node expects the container down. - the dashboard renders one row per node instead of one per agent. takes_container_down never reached the frontend; no wire change needed. 315 tests pass unchanged.
This commit is contained in:
parent
6809c782a3
commit
8ce265fdf0
6 changed files with 79 additions and 56 deletions
|
|
@ -1294,22 +1294,23 @@ impl Coordinator {
|
|||
/// crash-watch suppression is a separate, narrower thing
|
||||
/// ([`Coordinator::suppress_crash_watch`]); the pill comes back for free
|
||||
/// once those become real nodes.
|
||||
/// ⚠️ **A `Vec` per agent, not one entry.** `running_transients` tests
|
||||
/// status alone, so a lease-exempt `Prebuild` for `a` and a lease-holding
|
||||
/// `StopForUpdate` for `a` are both live pills. Collapsing them to one
|
||||
/// would pick arbitrarily and, for the crash watcher, silently lose a
|
||||
/// `deliberate_stop = true` behind a `false` — reporting an intentional
|
||||
/// stop as a crash.
|
||||
#[must_use]
|
||||
pub fn transient_snapshot(&self) -> HashMap<String, TransientState> {
|
||||
self.job_queue
|
||||
.running_transients()
|
||||
.into_iter()
|
||||
.map(|t| {
|
||||
(
|
||||
t.agent,
|
||||
TransientState {
|
||||
label: t.label,
|
||||
deliberate_stop: t.takes_container_down,
|
||||
since: t.since,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
pub fn transient_snapshot(&self) -> HashMap<String, Vec<TransientState>> {
|
||||
let mut out: HashMap<String, Vec<TransientState>> = HashMap::new();
|
||||
for t in self.job_queue.running_transients() {
|
||||
out.entry(t.agent).or_default().push(TransientState {
|
||||
label: t.label,
|
||||
deliberate_stop: t.takes_container_down,
|
||||
since: t.since,
|
||||
});
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Drop a system message into the given agent's inbox. Wakes the
|
||||
|
|
|
|||
Loading…
Reference in a new issue