feat(#2446): release a DAG's per-agent lease when that agent's subgraph is terminal
A per-agent lifecycle lease gates that agent's container globally across concurrent DAGs, so it should be held for exactly as long as the agent's work in a DAG is in flight, no longer. settle() previously freed every lease a DAG held only at whole-DAG terminal, so a multi-agent DAG (a hive-wide restart) kept agent A's container locked until B and C also finished, blocking any other DAG wanting A. Now free each agent's lease the moment its own subgraph within the DAG is terminal (no live node still targets it), and drop that agent's dashboard transient pill on the same edge via a new per-agent release channel. A single-agent DAG is unaffected: its agent's subgraph goes terminal exactly when the whole DAG does, so behaviour is identical.
This commit is contained in:
parent
9edd37501a
commit
9fdadb99c0
4 changed files with 136 additions and 25 deletions
|
|
@ -139,15 +139,25 @@ async fn handle_completion(
|
|||
coord.emit_rebuild_queue_snapshot();
|
||||
}
|
||||
|
||||
/// Drain buffered terminal roll-ups: drop each DAG's lease-window
|
||||
/// transient guard, then run the terminal hook (approval resolution,
|
||||
/// Drain per-agent lease releases and buffered terminal roll-ups.
|
||||
///
|
||||
/// Per-agent first: an agent's subgraph within a DAG went terminal (its
|
||||
/// lease was freed in `settle`), so drop that agent's `(dag, agent)`
|
||||
/// transient pill now — ahead of whole-DAG terminal for a multi-agent
|
||||
/// DAG. Then the whole-DAG terminals: drop any remaining transient the
|
||||
/// DAG still held and run the terminal hook (approval resolution,
|
||||
/// `Rebuilt` events, cancelled-power-op intent revert).
|
||||
async fn process_terminals(
|
||||
coord: &Arc<Coordinator>,
|
||||
transients: &mut HashMap<(u64, String), crate::coordinator::TransientGuard>,
|
||||
) {
|
||||
for rel in coord.job_queue.drain_agent_releases() {
|
||||
transients.remove(&(rel.dag_id, rel.agent));
|
||||
}
|
||||
for terminal in coord.job_queue.drain_terminal() {
|
||||
// Drop every per-agent transient guard this DAG held.
|
||||
// Drop any per-agent transient guard the DAG still held (the
|
||||
// per-agent pass above already dropped the ones whose subgraphs
|
||||
// settled early).
|
||||
transients.retain(|(dag_id, _), _| *dag_id != terminal.dag_id);
|
||||
exec::on_dag_terminal(coord, &terminal).await;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue