diff --git a/hive-c0re/src/job_queue/mod.rs b/hive-c0re/src/job_queue/mod.rs index 4e2a7930..843b6d3c 100644 --- a/hive-c0re/src/job_queue/mod.rs +++ b/hive-c0re/src/job_queue/mod.rs @@ -89,22 +89,14 @@ pub struct RunningTransient { pub since: DateTime, } -/// An owned read-view of a DAG container's carried metadata ([`NodeKind::Dag`]). -/// Derived on read from the container node — the data has a single home (the -/// node payload); this is not a stored side-table. -struct DagMeta { - source: Source, - reason: String, - created_at: DateTime, -} - /// The crate scheduler, specialised to this host's node + resource types. /// /// A **DAG is a single container node** ([`NodeKind::Dag`], `parent = None`) /// whose subtree is the DAG's work — so the container's `NodeId` is the DAG id, /// its rolled-up state is the DAG state, and there are no grouping side-tables: -/// membership + meta are graph queries ([`container`] / [`dag_meta`] + the -/// `hive_jobq::Graph` accessors). One shared crate [`Graph`] holds every DAG. +/// membership + meta are graph queries ([`container`] + the `hive_jobq::Graph` +/// accessors, with the meta read straight off the container's payload). One +/// shared crate [`Graph`] holds every DAG. /// /// There is deliberately **no wrapper struct and no per-node side map**. The /// last map held the `build_logs` row id; that link now lives on the log row @@ -400,25 +392,6 @@ fn container(sched: &Sched, dag_id: u64) -> Option { }) } -/// The container's carried domain metadata as an owned read-view. The data -/// lives solely in the [`NodeKind::Dag`] payload — this is a derived read, -/// not a stored side-table. -fn dag_meta(sched: &Sched, container: NodeId) -> Option { - let NodeKind::Dag { - source, - reason, - created_at, - } = &sched.graph().node(container)?.payload - else { - return None; - }; - Some(DagMeta { - source: *source, - reason: reason.clone(), - created_at: *created_at, - }) -} - /// Project a DAG into its wire [`DagView`]: a near-raw view of the /// container's work nodes, with `Done` nodes excluded. Lifecycle /// (`state` / `started_at` / `finished_at` / `error`) is read straight @@ -429,7 +402,17 @@ fn dag_meta(sched: &Sched, container: NodeId) -> Option { /// DAG drops out of the snapshot entirely (a `Failed` one lingers until /// aged out). fn dag_view(sched: &Sched, container: NodeId) -> Option { - let meta = dag_meta(sched, container)?; + // Read straight off the container's payload: the three fields have a + // single home there, so an intermediate owned copy of them was a second + // type describing the same data rather than a grouping side-table. + let NodeKind::Dag { + source, + reason, + created_at, + } = &sched.graph().node(container)?.payload + else { + return None; + }; let all: Vec<_> = sched.graph().descendants(container).collect(); // DAG-level timestamps are taken over *all* subtree nodes (including the // `Done` ones excluded from the wire) — the client can't derive them @@ -504,9 +487,9 @@ fn dag_view(sched: &Sched, container: NodeId) -> Option { let is_terminal = sched.graph().is_settled(container) == Some(true); Some(DagView { id: container.get(), - source: meta.source, - reason: meta.reason.clone(), - created_at: meta.created_at, + source: *source, + reason: reason.clone(), + created_at: *created_at, started_at: started.into_iter().min(), finished_at: is_terminal.then(|| finished.into_iter().max()).flatten(), nodes,