jobq: templates swallow the DagSpec layer
DagSpec described the graph the templates were about to build, one layer below the templates themselves. Per #2972 the templates should be that unit, so the spec type is gone and every declarer writes onto the job builder directly. - delete DagSpec<F> and its hand-written Debug impl - submit(source, reason, declare: impl FnOnce(&Job)) replaces the pre-built-spec signature; submit_and_emit follows - all six templates take &Job; the Source is now the caller's to pass, which spawn and approval_deploy previously hardcoded while the other four did not - power_dag dissolves into stop_nodes/start_nodes/restart_nodes, which borrow their targets instead of owning them 315 tests pass unchanged.
This commit is contained in:
parent
96ef592fee
commit
6899f574f6
7 changed files with 347 additions and 550 deletions
|
|
@ -426,44 +426,3 @@ impl NodeKind {
|
|||
// - `DeployWindow` brackets a deploy without itself stopping anything.
|
||||
}
|
||||
}
|
||||
|
||||
/// Submit-time spec for a whole DAG: the group's metadata plus the declared —
|
||||
/// not yet inserted — nodes. Built by `templates.rs`, inserted by
|
||||
/// `JobQueue::submit`.
|
||||
///
|
||||
/// No DAG-level `agent` — every node carries its own (a DAG can span agents),
|
||||
/// and the queue derives per-agent leasing from [`NodeKind::agent`].
|
||||
/// Type-specific payloads (`PermChange`'s file payload) ride the node that
|
||||
/// consumes them ([`NodeKind::WritePermFile`]), not this generic spec.
|
||||
///
|
||||
/// There is no separate per-node spec type, and no built job either: `declare`
|
||||
/// is a *recipe* the queue runs against a builder `hive_jobq` owns, at the
|
||||
/// moment it inserts. A shape that has been declared is therefore always
|
||||
/// insertable — a dangling edge or a cycle cannot be expressed, so there is
|
||||
/// nothing left for a submit-time validation pass to reject.
|
||||
///
|
||||
/// Generic over the recipe rather than boxing it: a spec goes from the template
|
||||
/// that returns it straight to the `submit` that consumes it, so the closure's
|
||||
/// concrete type is known the whole way and needs neither an allocation nor a
|
||||
/// `Send` bound. Nothing boxes a recipe any more — a running node grows its DAG
|
||||
/// by declaring straight onto the builder it was handed, so there is no recipe
|
||||
/// to store and replay across a task boundary.
|
||||
pub struct DagSpec<F> {
|
||||
pub source: Source,
|
||||
/// Free-form "why".
|
||||
pub reason: String,
|
||||
/// Declares the DAG's nodes — their edges, grouping and resources — onto
|
||||
/// the builder the queue hands it.
|
||||
pub declare: F,
|
||||
}
|
||||
|
||||
impl<F> std::fmt::Debug for DagSpec<F> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// The recipe is a closure; there is nothing to show of it, and its
|
||||
// nodes do not exist until the queue runs it.
|
||||
f.debug_struct("DagSpec")
|
||||
.field("source", &self.source)
|
||||
.field("reason", &self.reason)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue