feat(#2453): remove DAG parent_id now that every op is one DAG
With the meta-update cascade (#2476) and startup sweep (#2450) folded into single DAGs that grow per-agent subgraphs via append_subgraph, nothing links parent/child DAGs anymore — parent_id is dead. hive-c0re: drop parent_id from Dag/DagSpec (+ the DagView copy); delete append_children and cancel_children (no callers); simplify trim_history (no more terminal-parent-with-live-children guard — a one-big-DAG is terminal only when its whole graph settles); drop the rebuild() parent_id param; QueueDag returns just the polled DAG (no fan-out children to gather). hive-sh4re: drop the DagView.parent_id wire field. frontend: a multi-step op is one DAG now, so renderRebuildQueue drops the childrenOf/orphans cross-DAG grouping and renders each entry flat; its per-agent subgraphs render as nodes within the one row (split by deps). Removed the dead rqe-child style + isChild plumbing. Docs + the child-DAG queue tests updated/removed to match.
This commit is contained in:
parent
2b3130f63c
commit
edf9fd036e
15 changed files with 40 additions and 337 deletions
|
|
@ -1,7 +1,8 @@
|
|||
//! Queue-core unit tests: submit / no-dedup, cycle rejection, resource
|
||||
//! serialization (build slots / per-agent leases), lease-exempt
|
||||
//! overlap, FIFO fairness, cancel semantics, `AfterAny` failure
|
||||
//! routing, fan-out, and history retention. All synchronous — the
|
||||
//! routing, in-DAG subgraph growth, and history retention. All
|
||||
//! synchronous — the
|
||||
//! scheduler's async loop is a thin claim/complete pump over the same
|
||||
//! methods exercised here.
|
||||
|
||||
|
|
@ -13,7 +14,7 @@ fn submit(q: &JobQueue, spec: DagSpec) -> u64 {
|
|||
}
|
||||
|
||||
fn rebuild(agent: &str, reason: &str) -> DagSpec {
|
||||
templates::rebuild(agent, Source::Manual, reason.to_owned(), None, true)
|
||||
templates::rebuild(agent, Source::Manual, reason.to_owned(), true)
|
||||
}
|
||||
|
||||
/// Restart DAG spec with every agent treated as **running** — the online
|
||||
|
|
@ -460,7 +461,6 @@ fn append_subgraph_roots_on_emitter_and_rebases_local_deps() {
|
|||
template: Template::Boot,
|
||||
source: Source::AutoUpdate,
|
||||
reason: "sweep".to_owned(),
|
||||
parent_id: None,
|
||||
approval_id: None,
|
||||
inputs: Vec::new(),
|
||||
perm_payload: None,
|
||||
|
|
@ -646,125 +646,6 @@ fn cancel_refuses_running_dag() {
|
|||
assert_eq!(state_of(&q, id), State::Running);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_children_marks_queued_children_only() {
|
||||
let q = JobQueue::new(1);
|
||||
let meta = submit(
|
||||
&q,
|
||||
templates::meta_update(vec![], Source::Manual, "bump".to_owned(), None),
|
||||
);
|
||||
// Parent's MetaLock is running while children exist.
|
||||
let lock = claim_one(&q);
|
||||
assert_eq!(lock.dag_id, meta);
|
||||
let child_a = submit(
|
||||
&q,
|
||||
templates::rebuild(
|
||||
"agent-a",
|
||||
Source::MetaUpdate,
|
||||
"cascade".to_owned(),
|
||||
Some(meta),
|
||||
false,
|
||||
),
|
||||
);
|
||||
let child_b = submit(
|
||||
&q,
|
||||
templates::rebuild(
|
||||
"agent-b",
|
||||
Source::MetaUpdate,
|
||||
"cascade".to_owned(),
|
||||
Some(meta),
|
||||
false,
|
||||
),
|
||||
);
|
||||
let unrelated = submit(&q, rebuild("agent-c", "operator queued"));
|
||||
// MetaLock holds the single build slot, so both children (and the
|
||||
// unrelated rebuild) are still fully queued here.
|
||||
let cancelled = q.cancel_children(meta);
|
||||
assert_eq!(cancelled, 2);
|
||||
assert_eq!(state_of(&q, child_a), State::Cancelled);
|
||||
assert_eq!(state_of(&q, child_b), State::Cancelled);
|
||||
assert_eq!(state_of(&q, unrelated), State::Queued);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_children_skips_running_child() {
|
||||
let q = JobQueue::new(2);
|
||||
let meta = submit(
|
||||
&q,
|
||||
templates::meta_update(vec![], Source::Manual, "bump".to_owned(), None),
|
||||
);
|
||||
let lock = claim_one(&q);
|
||||
let running_child = submit(
|
||||
&q,
|
||||
templates::rebuild(
|
||||
"agent-a",
|
||||
Source::MetaUpdate,
|
||||
"cascade".to_owned(),
|
||||
Some(meta),
|
||||
false,
|
||||
),
|
||||
);
|
||||
let queued_child = submit(
|
||||
&q,
|
||||
templates::rebuild(
|
||||
"agent-b",
|
||||
Source::MetaUpdate,
|
||||
"cascade".to_owned(),
|
||||
Some(meta),
|
||||
false,
|
||||
),
|
||||
);
|
||||
// Second slot lets running_child's prebuild start.
|
||||
let child_claim = claim_one(&q);
|
||||
assert_eq!(child_claim.dag_id, running_child);
|
||||
let n = q.cancel_children(meta);
|
||||
assert_eq!(n, 1);
|
||||
assert_eq!(state_of(&q, running_child), State::Running);
|
||||
assert_eq!(state_of(&q, queued_child), State::Cancelled);
|
||||
q.complete_node(meta, lock.node_id, Ok(()));
|
||||
}
|
||||
|
||||
// ---- fan-out ----
|
||||
|
||||
#[test]
|
||||
fn append_children_sets_parent() {
|
||||
let q = JobQueue::new(1);
|
||||
let meta = submit(
|
||||
&q,
|
||||
templates::meta_update(vec![], Source::Manual, "bump".to_owned(), None),
|
||||
);
|
||||
let specs = vec![
|
||||
templates::rebuild(
|
||||
"alice",
|
||||
Source::MetaUpdate,
|
||||
"cascade".to_owned(),
|
||||
Some(meta),
|
||||
false,
|
||||
),
|
||||
templates::rebuild(
|
||||
"bob",
|
||||
Source::MetaUpdate,
|
||||
"cascade".to_owned(),
|
||||
Some(meta),
|
||||
false,
|
||||
),
|
||||
// No dedup: a second alice child is its own DAG now.
|
||||
templates::rebuild(
|
||||
"alice",
|
||||
Source::MetaUpdate,
|
||||
"cascade again".to_owned(),
|
||||
Some(meta),
|
||||
false,
|
||||
),
|
||||
];
|
||||
let ids = q.append_children(specs);
|
||||
assert_eq!(ids.len(), 3);
|
||||
assert_ne!(ids[0], ids[2], "no dedup: duplicate child is distinct");
|
||||
let snap = q.snapshot();
|
||||
let children: Vec<_> = snap.iter().filter(|d| d.parent_id == Some(meta)).collect();
|
||||
assert_eq!(children.len(), 3);
|
||||
}
|
||||
|
||||
// ---- terminal reporting + lease release ----
|
||||
|
||||
#[test]
|
||||
|
|
@ -826,88 +707,6 @@ fn cancelled_dag_reports_terminal_once() {
|
|||
assert!(q.drain_terminal().iter().all(|t| t.dag_id != id));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_children_reports_terminals() {
|
||||
let q = JobQueue::new(1);
|
||||
let meta = submit(
|
||||
&q,
|
||||
templates::meta_update(vec![], Source::Manual, "bump".to_owned(), None),
|
||||
);
|
||||
let _lock = claim_one(&q);
|
||||
let child = submit(
|
||||
&q,
|
||||
templates::rebuild(
|
||||
"agent-a",
|
||||
Source::MetaUpdate,
|
||||
"cascade".to_owned(),
|
||||
Some(meta),
|
||||
false,
|
||||
),
|
||||
);
|
||||
assert_eq!(q.cancel_children(meta), 1);
|
||||
let reports = q.drain_terminal();
|
||||
assert_eq!(reports.len(), 1);
|
||||
assert_eq!(reports[0].dag_id, child);
|
||||
assert_eq!(reports[0].state, State::Cancelled);
|
||||
}
|
||||
|
||||
/// History trim must not evict a terminal fan-out parent while its
|
||||
/// children are still live — the dashboard groups children under it.
|
||||
#[test]
|
||||
fn trim_keeps_terminal_parent_with_live_children() {
|
||||
let q = JobQueue::new(1);
|
||||
// Pin agent-x's lease with a running stop DAG so the child below
|
||||
// stays fully queued while we churn history.
|
||||
let pin = submit(
|
||||
&q,
|
||||
templates::reconcile_only(
|
||||
Template::Stop,
|
||||
"agent-x",
|
||||
Source::Manual,
|
||||
"lease pin".to_owned(),
|
||||
None,
|
||||
),
|
||||
);
|
||||
let pin_claim = claim_one(&q);
|
||||
assert_eq!(pin_claim.dag_id, pin);
|
||||
// Terminal fan-out parent + a lease-blocked child under it.
|
||||
let meta = submit(
|
||||
&q,
|
||||
templates::meta_update(vec![], Source::Manual, "bump".to_owned(), None),
|
||||
);
|
||||
let lock = claim_one(&q);
|
||||
q.complete_node(meta, lock.node_id, Ok(()));
|
||||
let mut child_spec = submit::restart_spec(
|
||||
&[("agent-x".to_owned(), true)],
|
||||
false,
|
||||
Source::MetaUpdate,
|
||||
"cascade".to_owned(),
|
||||
);
|
||||
child_spec.parent_id = Some(meta);
|
||||
let child = submit(&q, child_spec);
|
||||
// Churn > MAX_HISTORY_PER_TEMPLATE terminal meta_update DAGs.
|
||||
for i in 0..7 {
|
||||
let id = submit(
|
||||
&q,
|
||||
templates::meta_update(
|
||||
vec![format!("input-{i}")],
|
||||
Source::Manual,
|
||||
"churn".to_owned(),
|
||||
None,
|
||||
),
|
||||
);
|
||||
let c = claim_one(&q);
|
||||
assert_eq!(c.dag_id, id, "child is lease-blocked; churn claims freely");
|
||||
q.complete_node(id, c.node_id, Ok(()));
|
||||
}
|
||||
let snap = q.snapshot();
|
||||
assert!(
|
||||
snap.iter().any(|d| d.id == meta),
|
||||
"terminal parent with live child must survive trim"
|
||||
);
|
||||
assert!(snap.iter().any(|d| d.id == child));
|
||||
}
|
||||
|
||||
// ---- steps, build logs, history ----
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Reference in a new issue