job_queue: add NodeKind::Reparent (topology moves as a queue node, #2719)
This commit is contained in:
parent
766b1f71fb
commit
05b373474a
6 changed files with 177 additions and 5 deletions
|
|
@ -13,6 +13,10 @@ fn submit(q: &JobQueue, spec: DagSpec) -> u64 {
|
|||
q.submit(spec).expect("valid spec")
|
||||
}
|
||||
|
||||
fn ident(s: &str) -> hive_types::Ident {
|
||||
hive_types::Ident::parse(s).expect("valid test ident")
|
||||
}
|
||||
|
||||
fn rebuild(agent: &str, reason: &str) -> DagSpec {
|
||||
templates::rebuild(agent, Source::Manual, reason.to_owned(), true)
|
||||
}
|
||||
|
|
@ -1357,3 +1361,52 @@ fn perm_change_shape_prefixes_rebuild_chain() {
|
|||
}
|
||||
assert_eq!(state_of(&q, id), State::Done);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reparent_shape_is_a_lone_agentless_meta_window_node() {
|
||||
// Single-move `set-parent` shape: one node, no rebuild subgraph (no
|
||||
// container rebuild needed for a parent move), agentless like
|
||||
// `MetaLock`, and it must declare the meta window — a topology commit
|
||||
// must not land inside another node's staged deploy window.
|
||||
let q = JobQueue::new(1);
|
||||
let id = submit(
|
||||
&q,
|
||||
templates::reparent(
|
||||
vec![(ident("alice"), Some(ident("bob")))],
|
||||
Source::Manual,
|
||||
"set-parent".to_owned(),
|
||||
),
|
||||
);
|
||||
let c = claim_one(&q);
|
||||
assert_eq!(c.kind.as_str(), "reparent");
|
||||
assert_eq!(c.agent, "", "Reparent is agentless — no per-agent lease");
|
||||
assert!(
|
||||
c.kind.needs_meta_window(),
|
||||
"a topology commit must hold the same MetaWindow as WritePermFile"
|
||||
);
|
||||
assert!(!c.kind.needs_lease());
|
||||
assert!(!c.kind.needs_build_slot());
|
||||
q.complete_node(id, c.node_id, Ok(()));
|
||||
assert_eq!(state_of(&q, id), State::Done);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reparent_bulk_shape_carries_every_move_on_one_node() {
|
||||
// `set-parent-bulk`: still ONE node (one git commit, `moves.len() > 1`),
|
||||
// not one node per move — bulk atomicity across every move in the
|
||||
// request is the reason a single node was chosen in the first place.
|
||||
let moves = vec![(ident("alice"), Some(ident("bob"))), (ident("carol"), None)];
|
||||
let q = JobQueue::new(1);
|
||||
let id = submit(
|
||||
&q,
|
||||
templates::reparent(moves.clone(), Source::Manual, "set-parent-bulk".to_owned()),
|
||||
);
|
||||
let c = claim_one(&q);
|
||||
assert_eq!(c.kind.as_str(), "reparent");
|
||||
let NodeKind::Reparent { moves: got } = &c.kind else {
|
||||
panic!("expected a Reparent node, got {:?}", c.kind);
|
||||
};
|
||||
assert_eq!(got, &moves);
|
||||
q.complete_node(id, c.node_id, Ok(()));
|
||||
assert_eq!(state_of(&q, id), State::Done);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue