feat(#2591): auto-complete the DAG container + run terminal hooks inline
This commit is contained in:
parent
a78280feed
commit
2294cd4516
4 changed files with 59 additions and 78 deletions
|
|
@ -312,6 +312,11 @@ impl JobQueue {
|
|||
.map_err(|e| anyhow::anyhow!("job_queue: container insert failed: {e}"))?;
|
||||
inner.node_rt.insert(container, NodeRuntime::default());
|
||||
insert_group(&mut inner, &spec.nodes, Some(container))?;
|
||||
// Settle the container's own (no-op) logic immediately so it parks in
|
||||
// `Finishing` and its children become runnable — it never needs claiming
|
||||
// or executing, and stays out of `claim_ready`. It rolls up terminal when
|
||||
// its whole subtree settles (that's the DAG-done signal).
|
||||
inner.sched.complete(container, Outcome::Done);
|
||||
drop(inner);
|
||||
self.notify.notify_one();
|
||||
Ok(container.get())
|
||||
|
|
@ -434,21 +439,17 @@ impl JobQueue {
|
|||
terminal
|
||||
}
|
||||
|
||||
/// Cancel a DAG that hasn't started yet: the container + every work node is
|
||||
/// still `Pending`, so each is cancelled. No-op (`false`) once any node is
|
||||
/// running or terminal — an in-flight nix build isn't interruptible. The
|
||||
/// cancel rolls the container up to `Cancelled`, so its inline hook (approval
|
||||
/// resolution, power-intent revert) still fires.
|
||||
pub fn cancel(&self, dag_id: u64) -> bool {
|
||||
/// Cancel a DAG that hasn't started yet: every work node is still `Pending`,
|
||||
/// so each is cancelled. `None` once any work node is running or terminal —
|
||||
/// an in-flight nix build isn't interruptible. Otherwise the container is
|
||||
/// rolled up so the DAG settles (wire state `Cancelled`) and its terminal
|
||||
/// summary is returned — the caller fires the inline hook (power-intent
|
||||
/// revert / approval resolution) off it.
|
||||
pub fn cancel(&self, dag_id: u64) -> Option<TerminalDag> {
|
||||
let mut inner = self.lock();
|
||||
let inner = &mut *inner;
|
||||
let Some(container) = inner.container(dag_id) else {
|
||||
return false;
|
||||
};
|
||||
let ids: Vec<NodeId> = std::iter::once(container)
|
||||
.chain(inner.subtree(container))
|
||||
.collect();
|
||||
let all_pending = ids.iter().all(|&id| {
|
||||
let container = inner.container(dag_id)?;
|
||||
let work = inner.subtree(container);
|
||||
let all_pending = work.iter().all(|&id| {
|
||||
inner
|
||||
.sched
|
||||
.graph()
|
||||
|
|
@ -456,13 +457,18 @@ impl JobQueue {
|
|||
.is_some_and(|n| n.state == JobState::Pending)
|
||||
});
|
||||
if !all_pending {
|
||||
return false;
|
||||
return None;
|
||||
}
|
||||
for id in ids {
|
||||
for id in work {
|
||||
inner.sched.cancel_node(id);
|
||||
}
|
||||
// Roll the container up so the DAG reaches a terminal state (all children
|
||||
// now `Cancelled`); `dag_rollup` reports `Cancelled` to the wire.
|
||||
inner.sched.complete(container, Outcome::Done);
|
||||
let terminal = inner.terminal_dag(container);
|
||||
drop(inner);
|
||||
self.notify.notify_one();
|
||||
true
|
||||
terminal
|
||||
}
|
||||
|
||||
/// Set the step label on a `Running` node. Returns `true` when it changed.
|
||||
|
|
|
|||
Loading…
Reference in a new issue