From 39299c60351d4252f0be57a7151f623c67458f9e Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 3 Aug 2026 01:42:27 +0200 Subject: [PATCH] jobq: read DAG metadata off the container payload, drop DagMeta DagMeta was three fields copied out of the NodeKind::Dag payload and read back out in one place; its own docstring conceded the data's single home is the payload. dag_view now destructures the payload directly. The borrow stays immutable alongside the existing descendants() borrow, so nothing needed cloning beyond the reason String the DagView field already required. 315 tests pass unchanged. --- hive-c0re/src/job_queue/mod.rs | 51 ++++++++++++---------------------- 1 file changed, 17 insertions(+), 34 deletions(-) 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,