jobq: rename the builder parameters too, not just the alias
Renaming `pub type Job` fixed the definition and left every use site reading `b` and `job` — including `job: super::JobBuilder`, where the parameter still asserted it was a job while its type said otherwise. The propagation is what the issue was about, so the parameters are the half that matters at a call site. Two spots deliberately untouched: `auto_update`'s `sort_by(|a, b| …)` comparator, and the prose that means the job *queue* (main.rs's "Job-queue scheduler", scheduler.rs's "not this module's job any more", the "grown job rejected" log). 315 tests pass unchanged.
This commit is contained in:
parent
379c9bb570
commit
684f6da78e
6 changed files with 203 additions and 180 deletions
|
|
@ -36,9 +36,9 @@ use super::{Handle, JobBuilder};
|
|||
///
|
||||
/// Exactly one runs on a DAG that executed, and neither runs on one the operator
|
||||
/// dropped — see [`hive_jobq::NodeRef::on_elimination_of`].
|
||||
fn emit_rebuilt_tails(b: &JobBuilder, agent: &str, roots: &[Handle<'_>]) {
|
||||
fn emit_rebuilt_tails(builder: &JobBuilder, agent: &str, roots: &[Handle<'_>]) {
|
||||
let ok = roots.iter().fold(
|
||||
b.node(NodeKind::EmitRebuilt {
|
||||
builder.node(NodeKind::EmitRebuilt {
|
||||
agent: agent.to_owned(),
|
||||
ok: true,
|
||||
}),
|
||||
|
|
@ -51,11 +51,12 @@ fn emit_rebuilt_tails(b: &JobBuilder, agent: &str, roots: &[Handle<'_>]) {
|
|||
// `Reconcile` is still bringing the container back up, so reporting straight
|
||||
// off the elimination would announce the failure mid-recovery.
|
||||
let _failed = roots.iter().fold(
|
||||
b.node(NodeKind::EmitRebuilt {
|
||||
agent: agent.to_owned(),
|
||||
ok: false,
|
||||
})
|
||||
.on_elimination_of(ok),
|
||||
builder
|
||||
.node(NodeKind::EmitRebuilt {
|
||||
agent: agent.to_owned(),
|
||||
ok: false,
|
||||
})
|
||||
.on_elimination_of(ok),
|
||||
hive_jobq::NodeRef::after_any,
|
||||
);
|
||||
}
|
||||
|
|
@ -65,13 +66,13 @@ fn emit_rebuilt_tails(b: &JobBuilder, agent: &str, roots: &[Handle<'_>]) {
|
|||
///
|
||||
/// The `Cancelled` node is what keeps a dropped approval DAG from dangling its
|
||||
/// row forever — its edge is the only one [`super::JobQueue::cancel`] spares.
|
||||
fn resolve_approval_tails(b: &JobBuilder, approval_id: i64, root: Handle<'_>) {
|
||||
fn resolve_approval_tails(builder: &JobBuilder, approval_id: i64, root: Handle<'_>) {
|
||||
for outcome in [
|
||||
TerminalState::Done,
|
||||
TerminalState::Failed,
|
||||
TerminalState::Cancelled,
|
||||
] {
|
||||
let _ = b
|
||||
let _ = builder
|
||||
.node(NodeKind::ResolveApproval {
|
||||
approval_id,
|
||||
outcome,
|
||||
|
|
@ -90,18 +91,18 @@ fn resolve_approval_tails(b: &JobBuilder, approval_id: i64, root: Handle<'_>) {
|
|||
///
|
||||
/// Same reason as [`fanned_out_mechanical`] for living here: this was the
|
||||
/// second construction site declaring nodes inline in an executor.
|
||||
pub(crate) fn grown_rebuilds(b: &JobBuilder, agents: &[String], relock: bool) {
|
||||
pub(crate) fn grown_rebuilds(builder: &JobBuilder, agents: &[String], relock: bool) {
|
||||
for agent in agents {
|
||||
rebuild_nodes(b, agent, relock, None);
|
||||
rebuild_nodes(builder, agent, relock, None);
|
||||
}
|
||||
}
|
||||
|
||||
/// As [`grown_rebuilds`], but each agent gets its `Signal` → `Drain` window
|
||||
/// before being stopped. The boot sweep's flavour: it stops agents that were
|
||||
/// mid-turn when the host came up, so they drain rather than being cut off.
|
||||
pub(crate) fn grown_graceful_rebuilds(b: &JobBuilder, agents: &[String], relock: bool) {
|
||||
pub(crate) fn grown_graceful_rebuilds(builder: &JobBuilder, agents: &[String], relock: bool) {
|
||||
for agent in agents {
|
||||
graceful_rebuild_nodes(b, agent, relock, None);
|
||||
graceful_rebuild_nodes(builder, agent, relock, None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,9 +118,9 @@ pub(crate) fn grown_graceful_rebuilds(b: &JobBuilder, agents: &[String], relock:
|
|||
/// declaration does: this is the one construction site that was hiding in an
|
||||
/// executor, which meant the only test of it had to re-declare the same two
|
||||
/// calls itself and would have kept passing if the executor changed.
|
||||
pub(crate) fn fanned_out_mechanical(b: &JobBuilder, kind: NodeKind) {
|
||||
pub(crate) fn fanned_out_mechanical(builder: &JobBuilder, kind: NodeKind) {
|
||||
let lease = Resource::Agent(kind.agent().to_owned());
|
||||
let _ = b.node(kind).needs(lease);
|
||||
let _ = builder.node(kind).needs(lease);
|
||||
}
|
||||
|
||||
/// The group-roots a [`rebuild_nodes`] subgraph exposes to its caller: what a
|
||||
|
|
@ -176,7 +177,7 @@ impl<'a> RebuildRoots<'a> {
|
|||
/// takes a fresh lease; the tiny gap is harmless — `Reconcile` converges to
|
||||
/// the persisted `wanted` idempotently.
|
||||
fn rebuild_subtree<'a>(
|
||||
b: &'a JobBuilder,
|
||||
builder: &'a JobBuilder,
|
||||
agent: &str,
|
||||
relock: bool,
|
||||
graceful: bool,
|
||||
|
|
@ -184,13 +185,13 @@ fn rebuild_subtree<'a>(
|
|||
) -> RebuildRoots<'a> {
|
||||
let a = || agent.to_owned();
|
||||
|
||||
let mut meta_sync = b
|
||||
let mut meta_sync = builder
|
||||
.node(NodeKind::MetaSync { agent: a(), relock })
|
||||
.needs(Resource::MetaWindow);
|
||||
if let Some(after) = after {
|
||||
meta_sync = meta_sync.after_ok(after);
|
||||
}
|
||||
let prebuild = b
|
||||
let prebuild = builder
|
||||
.node(NodeKind::Prebuild { agent: a() })
|
||||
.needs(Resource::BuildSlot)
|
||||
.after_ok(meta_sync);
|
||||
|
|
@ -198,27 +199,29 @@ fn rebuild_subtree<'a>(
|
|||
// The stop root hangs off `Prebuild` and owns the agent lease for
|
||||
// everything below it. `StopForUpdate` parents the swap pair either way.
|
||||
let stop_for_update = if graceful {
|
||||
let signal = b
|
||||
let signal = builder
|
||||
.node(NodeKind::Signal { agent: a() })
|
||||
.needs(Resource::Agent(a()))
|
||||
.part_of(prebuild);
|
||||
// `Drain` is a *child* of `Signal`, so the parent gate already orders
|
||||
// it — a child must not dep on its own parent (dep-scope).
|
||||
let drain = b
|
||||
let drain = builder
|
||||
.node(NodeKind::Drain { agent: a() })
|
||||
.needs(Resource::Agent(a()))
|
||||
.part_of(signal);
|
||||
b.node(NodeKind::StopForUpdate { agent: a() })
|
||||
builder
|
||||
.node(NodeKind::StopForUpdate { agent: a() })
|
||||
.needs(Resource::Agent(a()))
|
||||
.part_of(signal)
|
||||
.after_ok(drain)
|
||||
} else {
|
||||
b.node(NodeKind::StopForUpdate { agent: a() })
|
||||
builder
|
||||
.node(NodeKind::StopForUpdate { agent: a() })
|
||||
.needs(Resource::Agent(a()))
|
||||
.part_of(prebuild)
|
||||
};
|
||||
|
||||
let swap = b
|
||||
let swap = builder
|
||||
.node(NodeKind::Swap { agent: a() })
|
||||
.needs(Resource::BuildSlot)
|
||||
.needs(Resource::Agent(a()))
|
||||
|
|
@ -227,13 +230,13 @@ fn rebuild_subtree<'a>(
|
|||
// `StopForUpdate`, which holds it, so this is a re-entrant borrow — no
|
||||
// second unit, no deadlock. Declaring it is what stops the requirement
|
||||
// being true only of this one DAG shape.
|
||||
let _post_swap = b
|
||||
let _post_swap = builder
|
||||
.node(NodeKind::PostSwap { agent: a() })
|
||||
.needs(Resource::Agent(a()))
|
||||
.part_of(stop_for_update)
|
||||
.after_ok(swap);
|
||||
|
||||
let reconcile = b
|
||||
let reconcile = builder
|
||||
.node(NodeKind::Reconcile { agent: a() })
|
||||
.needs(Resource::Agent(a()))
|
||||
.after_any(prebuild);
|
||||
|
|
@ -250,12 +253,12 @@ fn rebuild_subtree<'a>(
|
|||
/// when given, is the node this subgraph chains behind. See
|
||||
/// [`rebuild_subtree`] for the structure.
|
||||
pub(crate) fn rebuild_nodes<'a>(
|
||||
b: &'a JobBuilder,
|
||||
builder: &'a JobBuilder,
|
||||
agent: &str,
|
||||
relock: bool,
|
||||
after: Option<Handle<'a>>,
|
||||
) -> RebuildRoots<'a> {
|
||||
rebuild_subtree(b, agent, relock, false, after)
|
||||
rebuild_subtree(builder, agent, relock, false, after)
|
||||
}
|
||||
|
||||
/// As [`rebuild_nodes`], but the agent gets a `Signal` → `Drain` window to
|
||||
|
|
@ -266,12 +269,12 @@ pub(crate) fn rebuild_nodes<'a>(
|
|||
/// *prepend* nodes — it **re-parents** the stop root, so a caller cannot
|
||||
/// declare it without being handed the internals. Only the boot sweep wants it.
|
||||
pub(crate) fn graceful_rebuild_nodes<'a>(
|
||||
b: &'a JobBuilder,
|
||||
builder: &'a JobBuilder,
|
||||
agent: &str,
|
||||
relock: bool,
|
||||
after: Option<Handle<'a>>,
|
||||
) -> RebuildRoots<'a> {
|
||||
rebuild_subtree(b, agent, relock, true, after)
|
||||
rebuild_subtree(builder, agent, relock, true, after)
|
||||
}
|
||||
|
||||
/// The rebuild subgraph a [`NodeKind::DeployApply`] grows into its own DAG once
|
||||
|
|
@ -298,9 +301,9 @@ pub(crate) fn graceful_rebuild_nodes<'a>(
|
|||
/// `DeployWindow`'s subtree — so the `MetaWindow` this subgraph's `MetaSync`
|
||||
/// and `FinalizeDeploy` declare is re-entered from the ancestor already holding
|
||||
/// it rather than deadlocking against it.
|
||||
pub(crate) fn deploy_rebuild_nodes(b: &JobBuilder, agent: &str, approval_id: i64) {
|
||||
let roots = rebuild_nodes(b, agent, false, None);
|
||||
let _finalize = b
|
||||
pub(crate) fn deploy_rebuild_nodes(builder: &JobBuilder, agent: &str, approval_id: i64) {
|
||||
let roots = rebuild_nodes(builder, agent, false, None);
|
||||
let _finalize = builder
|
||||
.node(NodeKind::FinalizeDeploy {
|
||||
agent: agent.to_owned(),
|
||||
approval_id,
|
||||
|
|
@ -321,9 +324,9 @@ pub(crate) fn deploy_rebuild_nodes(b: &JobBuilder, agent: &str, approval_id: i64
|
|||
/// whole `StopForUpdate`→`Swap`→`PostSwap` subtree, so those three cover every
|
||||
/// node. Edging `Reconcile` alone would not do: it is `AfterAny` `Prebuild`, so
|
||||
/// it reaches `Done` even after a failed swap and the tail would report success.
|
||||
pub fn rebuild(b: &JobBuilder, agent: &str, relock: bool) {
|
||||
let roots = rebuild_nodes(b, agent, relock, None);
|
||||
emit_rebuilt_tails(b, agent, &roots.all());
|
||||
pub fn rebuild(builder: &JobBuilder, agent: &str, relock: bool) {
|
||||
let roots = rebuild_nodes(builder, agent, relock, None);
|
||||
emit_rebuilt_tails(builder, agent, &roots.all());
|
||||
}
|
||||
|
||||
/// Approval-driven deploy (`MergeConfigPr`) as a phase subtree rather than the
|
||||
|
|
@ -351,7 +354,7 @@ pub fn rebuild(b: &JobBuilder, agent: &str, relock: bool) {
|
|||
///
|
||||
/// The window still spans the container build, as it must: `prepare_deploy`
|
||||
/// leaves `flake.lock` staged-uncommitted for the build's whole duration.
|
||||
pub fn approval_deploy(b: &JobBuilder, agent: &str, approval_id: i64) {
|
||||
pub fn approval_deploy(builder: &JobBuilder, agent: &str, approval_id: i64) {
|
||||
let a = || agent.to_owned();
|
||||
// The window is the widest holder in the tree: it brackets a nix
|
||||
// build (`BuildSlot`), takes the container down across the swap
|
||||
|
|
@ -359,7 +362,7 @@ pub fn approval_deploy(b: &JobBuilder, agent: &str, approval_id: i64) {
|
|||
// (`MetaWindow`). All three are held for its whole subtree, which
|
||||
// is what lets the appended rebuild's `MetaSync` and the
|
||||
// `FinalizeDeploy` re-enter rather than contend.
|
||||
let window = b
|
||||
let window = builder
|
||||
.node(NodeKind::DeployWindow {
|
||||
agent: a(),
|
||||
approval_id,
|
||||
|
|
@ -367,20 +370,20 @@ pub fn approval_deploy(b: &JobBuilder, agent: &str, approval_id: i64) {
|
|||
.needs(Resource::BuildSlot)
|
||||
.needs(Resource::Agent(a()))
|
||||
.needs(Resource::MetaWindow);
|
||||
let verify = b
|
||||
let verify = builder
|
||||
.node(NodeKind::MergeVerify {
|
||||
agent: a(),
|
||||
approval_id,
|
||||
})
|
||||
.part_of(window);
|
||||
let apply = b
|
||||
let apply = builder
|
||||
.node(NodeKind::DeployApply {
|
||||
agent: a(),
|
||||
approval_id,
|
||||
})
|
||||
.part_of(window)
|
||||
.after_ok(verify);
|
||||
let _tail = b
|
||||
let _tail = builder
|
||||
.node(NodeKind::DeployTail {
|
||||
agent: a(),
|
||||
approval_id,
|
||||
|
|
@ -388,7 +391,7 @@ pub fn approval_deploy(b: &JobBuilder, agent: &str, approval_id: i64) {
|
|||
.part_of(window)
|
||||
.after_any(apply);
|
||||
|
||||
resolve_approval_tails(b, approval_id, window);
|
||||
resolve_approval_tails(builder, approval_id, window);
|
||||
}
|
||||
|
||||
/// First-deploy spawn (approval-driven): `Provision` (proposed/applied
|
||||
|
|
@ -402,27 +405,27 @@ pub fn approval_deploy(b: &JobBuilder, agent: &str, approval_id: i64) {
|
|||
/// container was never created). Closed by a `ResolveApproval` tail root edged
|
||||
/// `AfterAny` onto `Provision` — the DAG's only other group-root, so its roll-up
|
||||
/// already carries the whole cascade.
|
||||
pub fn spawn(b: &JobBuilder, agent: &str, approval_id: i64) {
|
||||
pub fn spawn(builder: &JobBuilder, agent: &str, approval_id: i64) {
|
||||
let a = || agent.to_owned();
|
||||
let provision = b
|
||||
let provision = builder
|
||||
.node(NodeKind::Provision { agent: a() })
|
||||
.needs(Resource::MetaWindow);
|
||||
let create = b
|
||||
let create = builder
|
||||
.node(NodeKind::Create { agent: a() })
|
||||
.needs(Resource::BuildSlot)
|
||||
.needs(Resource::Agent(a()))
|
||||
.part_of(provision);
|
||||
let dropin = b
|
||||
let dropin = builder
|
||||
.node(NodeKind::WriteDropin { agent: a() })
|
||||
.needs(Resource::Agent(a()))
|
||||
.part_of(create);
|
||||
let _reconcile = b
|
||||
let _reconcile = builder
|
||||
.node(NodeKind::Reconcile { agent: a() })
|
||||
.needs(Resource::Agent(a()))
|
||||
.part_of(create)
|
||||
.after_ok(dropin);
|
||||
|
||||
resolve_approval_tails(b, approval_id, provision);
|
||||
resolve_approval_tails(builder, approval_id, provision);
|
||||
}
|
||||
|
||||
/// Perm change: commit the JSON file(s), then the rebuild subgraph so
|
||||
|
|
@ -430,16 +433,16 @@ pub fn spawn(b: &JobBuilder, agent: &str, approval_id: i64) {
|
|||
/// effect in the container. Group-roots are `WritePermFile` plus the rebuild
|
||||
/// subgraph's `MetaSync` / `Prebuild` / `Reconcile`, so the `EmitRebuilt` tail
|
||||
/// edges all four.
|
||||
pub fn perm_change(b: &JobBuilder, agent: &str, payload: PermPayload) {
|
||||
let write = b
|
||||
pub fn perm_change(builder: &JobBuilder, agent: &str, payload: PermPayload) {
|
||||
let write = builder
|
||||
.node(NodeKind::WritePermFile {
|
||||
agent: agent.to_owned(),
|
||||
payload,
|
||||
})
|
||||
.needs(Resource::MetaWindow);
|
||||
let roots = rebuild_nodes(b, agent, true, Some(write));
|
||||
let roots = rebuild_nodes(builder, agent, true, Some(write));
|
||||
emit_rebuilt_tails(
|
||||
b,
|
||||
builder,
|
||||
agent,
|
||||
&[write, roots.meta_sync, roots.prebuild, roots.reconcile],
|
||||
);
|
||||
|
|
@ -455,8 +458,8 @@ pub fn perm_change(b: &JobBuilder, agent: &str, payload: PermPayload) {
|
|||
/// so the "hyperhive" pseudo-agent gets no pill), giving each cascade agent
|
||||
/// crash-watch suppression during its `Swap` — the property the old child
|
||||
/// `Rebuild` DAGs carried via their own transient.
|
||||
pub fn meta_update(b: &JobBuilder, inputs: Vec<String>, approval_id: Option<i64>) {
|
||||
let lock = b
|
||||
pub fn meta_update(builder: &JobBuilder, inputs: Vec<String>, approval_id: Option<i64>) {
|
||||
let lock = builder
|
||||
.node(NodeKind::MetaLock {
|
||||
sweep: false,
|
||||
fanout: None,
|
||||
|
|
@ -470,7 +473,7 @@ pub fn meta_update(b: &JobBuilder, inputs: Vec<String>, approval_id: Option<i64>
|
|||
// group-root — whose roll-up covers the rebuild subgraphs `MetaLock`
|
||||
// grows into itself.
|
||||
if let Some(approval_id) = approval_id {
|
||||
resolve_approval_tails(b, approval_id, lock);
|
||||
resolve_approval_tails(builder, approval_id, lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -483,8 +486,8 @@ pub fn meta_update(b: &JobBuilder, inputs: Vec<String>, approval_id: Option<i64>
|
|||
/// checks), so a parent move needs no container rebuild to take effect.
|
||||
/// No transient pill either — the node is agentless (no lease to hang one
|
||||
/// off of) and near-instant. No tail node: the write is the whole effect.
|
||||
pub fn reparent(b: &JobBuilder, moves: Vec<(hive_types::Ident, Option<hive_types::Ident>)>) {
|
||||
let _reparent = b
|
||||
pub fn reparent(builder: &JobBuilder, moves: Vec<(hive_types::Ident, Option<hive_types::Ident>)>) {
|
||||
let _reparent = builder
|
||||
.node(NodeKind::Reparent { moves })
|
||||
.needs(Resource::MetaWindow);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue