Skip to main content

haz_exec/run_graph/
mod.rs

1//! Workspace-wide scheduler that turns a validated [`TaskGraph`]
2//! into a sequence of [`run_task`](crate::run_task) calls subject
3//! to the workspace's concurrency caps.
4//!
5//! The public surface is [`run_graph`]: a single async function
6//! that walks the graph, admits ready tasks in canonical
7//! `(ProjectName, TaskName)` order subject to the workspace's
8//! global cap (`EXEC-004`) and per-tag caps (`EXEC-005`), and
9//! threads each completed task's `(stdout, stderr)` content
10//! hashes into every downstream call so cache-key derivation has
11//! the predecessor-stream contribution it needs (`CACHE-007` /
12//! `DAG-017`).
13//!
14//! The loop is built on [`futures::stream::FuturesUnordered`].
15//! Each pushed future borrows `ctx` and owns a snapshot of the
16//! current predecessor map; awaiting completion returns the
17//! `(TaskId, Result<CompletedRecord, RunTaskError>)` pair so the
18//! main body can re-acquire its own mutable borrows. The
19//! `outcomes` map stores the broader [`RunOutcome`] sum
20//! (Completed wraps the record; Skipped lands once the cascade
21//! work in a follow-up commit wires the variant).
22//!
23//! Mutex composition (`EXEC-006` condition 3, `EXEC-007`) is
24//! delivered through a lookup-then-spawn pipeline: each admitted
25//! task first runs [`cache_lookup_phase`]; on a hit the
26//! scheduler records the outcome immediately, and on a miss it
27//! consults its live mutex hold set before acquiring the mutex and
28//! driving [`run_fresh`]. Cache hits never touch the hold set
29//! per `MUTEX-007`. A task whose mutex is incompatible after
30//! lookup is returned to `ready` per `MUTEX-005`, its slot is
31//! released, and the next admission round re-evaluates.
32//!
33//! Cancellation (`EXEC-012..015`), the formal `Skipped` state and
34//! its typed diagnostics (`EXEC-011`), runtime cycle / overlap
35//! detection (`EXEC-019..020`), and live-mode output
36//! presentation (`EXEC-016`) are all wired through this module
37//! alongside the lookup-then-spawn pipeline.
38//!
39//! [`TaskGraph`]: haz_dag::graph::TaskGraph
40
41pub(super) mod cascade;
42pub(super) mod cycle;
43pub(super) mod overlap;
44pub(super) mod scheduler;
45pub(super) mod state;
46pub(super) mod steps;
47
48#[cfg(test)]
49mod test_fixtures;
50
51pub use crate::run_graph::scheduler::{
52    RunGraphError, RunGraphOutcome, RuntimeInvariantViolation, run_graph,
53};