Status model and trigger rules
Status: open/planned · Kind: component · Audience: user
Summary
Section titled “Summary”-
The state model: a small status enum (
pending | running | success | failed | skipped) plus per-node trigger rules that decide “prerequisite satisfied” from parents’ statuses. -
A boolean “done” is insufficient — rules like
all_failed/none_skippedneed to know how a parent finished. -
Sub-capability of C-D2GO-readiness-scheduling.
Statement
Section titled “Statement”Readiness generalizes “all parents done” to “parents’ statuses satisfy this
node’s trigger rule.” That requires distinguishing outcomes, so state is a
small closed enum, not a boolean. Each node carries a trigger (default
AllSuccess), which the frontier consults. The common “here is what finished”
case stays a one-liner via a sugar that treats an id list as Success.
One trait, StatusSource, replaces both halves of the TypeScript design — the
state union and the tracker’s separate status(id) resolver. That is also the
documented adapter seam for deriving status from a caller’s own typed domain
model, so a consumer whose satisfaction rule is richer than five values maps it
once at the boundary rather than threading a translation through every call.
What it provides
Section titled “What it provides”NodeStatus:Pending | Running | Success | Failed | Skipped, serializing snake_case. A node the state source has never heard of readsPending.TriggerRulepresets (the Airflow set):AllSuccess(default),AllDone,AllFailed,OneSuccess,OneFailed,NoneFailed,NoneSkipped,Always, withTriggerRule::is_satisfied_by(&[NodeStatus]) -> boolas the predicate.- A
StatusSourcetrait as the single state seam.
use graph_scheduler::{Graph, NodeAttrs, NodeStatus, TriggerRule, get_ready};
let g = Graph::new() .add_node("deploy", NodeAttrs::new().trigger(TriggerRule::AllSuccess)) // the default .add_node("cleanup", NodeAttrs::new().trigger(TriggerRule::AllDone)); // runs even on failure
get_ready(&g, &state, &ReadyOptions::default());Inputs
Section titled “Inputs”- Per-node
trigger(optional; defaultAllSuccess). - Any
StatusSource: aBTreeMap<NodeId, NodeStatus>, theDone(Vec<NodeId>)id-list sugar, or a closureFn(&NodeId) -> NodeStatus.
Outputs
Section titled “Outputs”- The per-node readiness verdict consumed by the frontier (C-PC3N-push-readiness-frontier).
Underlying implementation
Section titled “Underlying implementation”- No code realizes this yet — the capability is planned. It lands with the crate
at
packages/rust/graph-scheduler/, the status model insrc/status.rs. Until the crate exists there is no anchor to record here. - These two types are owned here and imported elsewhere.
NodeStatusandTriggerRulewere first defined inpackages/rust/foreman, which conceded in its own doc comment thatNodeStatuswas the graph-scheduler enum. Ownership moves to this crate and foreman re-exports both fromforeman::dag, so there is one definition and no parity fixture to maintain. foreman’s ontogen build still emits the TypeScript projection over the imported types.
- The enum is closed for v1; custom outcomes map onto the five.
Runningexists so a dispatched-but-unfinished node is excluded from the next frontier (prevents double-dispatch). Boolean-vs-enum rationale inD-BPD8-graph-scheduler-api.