refactor(#2441): move agent field from DAG onto Node; drop dedup
Agent was a single field on Dag/DagSpec, making a DAG structurally one-agent — a multi-agent op could only ever be N separate DAGs. Move it onto Node/NodeSpec (and the NodeView wire type), drop it from Dag/DagSpec (and DagView): a DAG can now span agents. - lifecycle lease keys on the node's agent, still globally exclusive per agent across all DAGs (Inner.leases unchanged in shape). A DAG holds one lease per distinct agent it touches; settle() frees each at DAG-terminal (per-agent-subgraph early release is a follow-up, only observable with multi-agent DAGs). - transient guard keyed (dag_id, agent); cancel-revert + Rebuilt events walk TerminalDag.agents. - submit-time dedup removed (a multi-agent DAG has no single agent to key on); every submit enqueues a fresh DAG. Whether dedup needs reintroducing is tracked in a follow-up sub-issue. - templates gain a node(agent, kind, deps) helper stamping the agent onto every node; meta templates stamp "hyperhive". Templates stay single-agent in this PR — behaviour is unchanged, only the representation + wire shape. Multi-agent DAG emission (restart/restart-all/ broad stop+start as one DAG) and the SetWanted-as-a-node change are follow-ups off #2439.
This commit is contained in:
parent
91607f3896
commit
2a59f2f5fc
7 changed files with 223 additions and 356 deletions
|
|
@ -35,8 +35,10 @@ struct NodeDone {
|
|||
pub async fn run_worker(coord: Arc<Coordinator>) {
|
||||
let mut shutdown = coord.shutdown_rx();
|
||||
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<NodeDone>();
|
||||
// DAG id → transient guard held for the lease window.
|
||||
let mut transients: HashMap<u64, crate::coordinator::TransientGuard> = HashMap::new();
|
||||
// (DAG id, agent) → transient guard held for that agent's lease
|
||||
// window. Keyed per-agent so a multi-agent DAG shows one transient
|
||||
// pill per agent it touches.
|
||||
let mut transients: HashMap<(u64, String), crate::coordinator::TransientGuard> = HashMap::new();
|
||||
loop {
|
||||
// Terminal roll-ups can appear without a node completion —
|
||||
// the cancel surfaces settle DAGs directly and wake this loop
|
||||
|
|
@ -49,7 +51,10 @@ pub async fn run_worker(coord: Arc<Coordinator>) {
|
|||
if claim.lease_acquired
|
||||
&& let Some(kind) = claim.transient
|
||||
{
|
||||
transients.insert(claim.dag_id, coord.transient_guard(&claim.agent, kind));
|
||||
transients.insert(
|
||||
(claim.dag_id, claim.agent.clone()),
|
||||
coord.transient_guard(&claim.agent, kind),
|
||||
);
|
||||
}
|
||||
tracing::info!(
|
||||
dag = claim.dag_id,
|
||||
|
|
@ -88,7 +93,7 @@ pub async fn run_worker(coord: Arc<Coordinator>) {
|
|||
|
||||
async fn handle_completion(
|
||||
coord: &Arc<Coordinator>,
|
||||
transients: &mut HashMap<u64, crate::coordinator::TransientGuard>,
|
||||
transients: &mut HashMap<(u64, String), crate::coordinator::TransientGuard>,
|
||||
done: NodeDone,
|
||||
) {
|
||||
let NodeDone { claim, result } = done;
|
||||
|
|
@ -143,10 +148,11 @@ async fn handle_completion(
|
|||
/// `Rebuilt` events, cancelled-power-op intent revert).
|
||||
async fn process_terminals(
|
||||
coord: &Arc<Coordinator>,
|
||||
transients: &mut HashMap<u64, crate::coordinator::TransientGuard>,
|
||||
transients: &mut HashMap<(u64, String), crate::coordinator::TransientGuard>,
|
||||
) {
|
||||
for terminal in coord.job_queue.drain_terminal() {
|
||||
transients.remove(&terminal.dag_id);
|
||||
// Drop every per-agent transient guard this DAG held.
|
||||
transients.retain(|(dag_id, _), _| *dag_id != terminal.dag_id);
|
||||
exec::on_dag_terminal(coord, &terminal).await;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue