refactor(job-queue): a job is a recipe, not a value you carry
Follows the jobq change: a builder can no longer be constructed or inserted outside `hive_jobq`, so `DagSpec` cannot hold one. It carries a `Declare` — `Box<dyn FnOnce(&Job) + Send>` — and the queue runs it against a builder jobq owns, at the moment it inserts. `NodeOutput.append_subgraph` becomes `Vec<Declare>` for the same reason, and this is where the shape was always heading: that field's doc already said an executor "cannot reach the queue, so it hands the declaration back", while its type was a `Vec<Job>` the executor had built itself. The rejected `build_nodes -> Vec<NodeSpec>` was the first version of that escape hatch; a recipe is the last one, because there is no job-shaped value to hand over at all. Templates and the power-op assemblers move their owned data into the closure and are otherwise unchanged — `rebuild_nodes`, `node` and the tail helpers already took `&Job` and returned handles, so only each template's outermost frame moved. Two `Debug` impls are hand-written: a closure has nothing to show, and its nodes do not exist until the queue runs it. `NodeOutput` reports how many subgraphs were emitted, `DagSpec` its source and reason. `append_subgraph`'s `is_empty()` early-return is gone — you cannot ask a recipe whether it will declare anything without running it. It now inserts and returns an empty id list if nothing was declared, which takes the queue lock in a case that previously skipped it. The two in-DAG-growth tests build `Declare`s now, so they exercise the shape an executor actually produces rather than one only a test could construct. 45 job-queue tests unchanged and passing.
This commit is contained in:
parent
f7548e4535
commit
9c97365f8f
8 changed files with 336 additions and 284 deletions
|
|
@ -5,11 +5,14 @@
|
|||
//! than computing where that node landed, and there is no positional index to
|
||||
//! get wrong.
|
||||
//!
|
||||
//! **An insertion API, not a spec factory.** [`JobBuilder::insert_into`]
|
||||
//! consumes the builder and puts the nodes straight into a [`Graph`], returning
|
||||
//! the ids the graph minted. Nothing job-shaped comes back out — there is no
|
||||
//! intermediate node-description type to keep in sync with [`Graph::insert`]'s
|
||||
//! signature.
|
||||
//! **An insertion API, not a spec factory.** A builder is only ever handed to a
|
||||
//! closure by an insertion entry point ([`Graph::insert_job`],
|
||||
//! [`crate::scheduler::Scheduler::insert_job`]), which inserts the declared
|
||||
//! nodes and returns the ids the graph minted. It cannot be constructed, held
|
||||
//! or inserted from outside this crate, and there is no intermediate
|
||||
//! node-description type to keep in sync with [`Graph::insert`]'s signature —
|
||||
//! so a job has no representation that can be passed around instead of being
|
||||
//! inserted.
|
||||
//!
|
||||
//! **Payload-agnostic.** Generic over the same `N` and `R` as [`Graph`]: the
|
||||
//! builder knows nothing about what a node *does*, only how nodes relate.
|
||||
|
|
|
|||
Loading…
Reference in a new issue