hivectl: migrate dag_progress to hive-jobq-wire's generic GraphNode
This commit is contained in:
parent
d3f2d246e3
commit
10b0f640af
8 changed files with 272 additions and 175 deletions
|
|
@ -378,6 +378,30 @@ impl JobQueue {
|
|||
.filter_map(|c| dag_view(&inner, c))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// One DAG's container node plus its live subtree, as generic wire
|
||||
/// nodes — the `QueueNodes` polling surface behind `hivectl`'s
|
||||
/// wait/progress loop. Sibling of [`Self::snapshot`]
|
||||
/// (which serves the same graph through the typed `DagView`/`NodeView`
|
||||
/// projection for the dashboard's `/api/state.rebuild_queue`), this one
|
||||
/// goes through [`GraphWire::wire_snapshot`] instead — no `Done`-node
|
||||
/// filtering, no roll-up field (the root's own `state` answers that,
|
||||
/// see `hive_jobq_wire`'s doc comment).
|
||||
///
|
||||
/// Empty when `dag_id` names no DAG container in the graph. Today that
|
||||
/// only happens for a genuinely unknown id: nothing prunes the graph
|
||||
/// yet (bounded-prune is a Stage-C follow-up, see [`visible_dags`]), so
|
||||
/// a *completed* DAG's nodes keep riding here with a terminal `state`
|
||||
/// rather than disappearing — callers watching for "done" should read
|
||||
/// the root's `state`, not emptiness.
|
||||
#[must_use]
|
||||
pub fn dag_nodes(&self, dag_id: u64) -> Vec<GraphNode> {
|
||||
let inner = self.lock();
|
||||
let Some(root) = container(&inner, dag_id) else {
|
||||
return Vec::new();
|
||||
};
|
||||
inner.graph().wire_snapshot([root])
|
||||
}
|
||||
}
|
||||
|
||||
/// The container node of `dag_id` — the `NodeKind::Dag` root whose id equals
|
||||
|
|
|
|||
|
|
@ -308,6 +308,15 @@ impl hive_jobq_wire::WireNode for NodeKind {
|
|||
{
|
||||
data.insert("inputs".to_owned(), inputs.clone().into());
|
||||
}
|
||||
// The DAG container's own metadata — nowhere else on the wire, since
|
||||
// `GraphNode` carries no DAG-level fields (a group root is an
|
||||
// ordinary node). `hivectl` needs `source` for its progress line;
|
||||
// `reason` rides along for free rather than adding a second variant
|
||||
// later for the one field the first pass missed.
|
||||
if let NodeKind::Dag { source, reason, .. } = self {
|
||||
data.insert("source".to_owned(), source.as_str().into());
|
||||
data.insert("reason".to_owned(), reason.clone().into());
|
||||
}
|
||||
// Not in the payload at all — the build log is keyed on node identity
|
||||
// in a side table, which is why `data` is handed the id.
|
||||
if let Some(log) = crate::build_logs::global().and_then(|h| h.id_for_node(id)) {
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ async fn dispatch(req: &HostRequest, coord: Arc<Coordinator>) -> HostResponse {
|
|||
.collect();
|
||||
HostResponse::dags(dags)
|
||||
}
|
||||
HostRequest::QueueNodes { id } => HostResponse::nodes(coord.job_queue.dag_nodes(*id)),
|
||||
HostRequest::List => HostResponse::list(lifecycle::list().await?),
|
||||
// The agents root is ours and not world-traversable, so this
|
||||
// question is only answerable on this side of the socket —
|
||||
|
|
|
|||
Loading…
Reference in a new issue