Skip to content

Status model and trigger rules

Status: open/planned · Kind: component · Audience: user

  • 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_skipped need to know how a parent finished.

  • Sub-capability of C-D2GO-readiness-scheduling.

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.

  • NodeStatus: Pending | Running | Success | Failed | Skipped, serializing snake_case. A node the state source has never heard of reads Pending.
  • TriggerRule presets (the Airflow set): AllSuccess (default), AllDone, AllFailed, OneSuccess, OneFailed, NoneFailed, NoneSkipped, Always, with TriggerRule::is_satisfied_by(&[NodeStatus]) -> bool as the predicate.
  • A StatusSource trait 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());
  • Per-node trigger (optional; default AllSuccess).
  • Any StatusSource: a BTreeMap<NodeId, NodeStatus>, the Done(Vec<NodeId>) id-list sugar, or a closure Fn(&NodeId) -> NodeStatus.
  • No code realizes this yet — the capability is planned. It lands with the crate at packages/rust/graph-scheduler/, the status model in src/status.rs. Until the crate exists there is no anchor to record here.
  • These two types are owned here and imported elsewhere. NodeStatus and TriggerRule were first defined in packages/rust/foreman, which conceded in its own doc comment that NodeStatus was the graph-scheduler enum. Ownership moves to this crate and foreman re-exports both from foreman::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. Running exists so a dispatched-but-unfinished node is excluded from the next frontier (prevents double-dispatch). Boolean-vs-enum rationale in D-BPD8-graph-scheduler-api.

← Back to Capabilities