jobq: delete DagView/NodeView, the second projection of one graph
Two views of the same graph existed: the typed `DagView`/`NodeView` (`/api/state.rebuild_queue`, the `QueueDag` socket request, and the `RebuildQueueChanged` payload) and `hive-jobq-wire`'s generic `GraphNode` (`/api/jobq/graph`, `QueueNodes`). Every consumer has moved to the generic one, so the typed pair is deleted rather than kept in agreement with it. What that removes, beyond the types: the `QueueDag` request and `HostResponse::dags`; `Queue::snapshot`; `dag_view`, `visible_dags`, `shown_on_wire`, `dag_finished_at` and `containers`; and the `rebuild_queue` field on `/api/state`. `RebuildQueueChanged` keeps its seq and loses its payload — nothing read it, and shipping the graph both on an event and on an endpoint is the duplication this issue is about. It stays an event rather than becoming a poll because push-on-change is what every other live surface here does. Two behaviours came out simpler for a structural reason. `await_dags` needed two rules — settled means "gone from the snapshot" *or* "present with every node terminal" — because the typed view evicted finished groups; the generic view doesn't, so pending is just "some node isn't terminal". And `state_of` in the tests no longer derives a roll-up at all: a group root's own state is the scheduler's answer. That second one found a bug. `cancelled_dag_still_runs_its_approval tail` asserted the group reads `Cancelled` while the tail it exists to protect was still pending — `rollup_state` flattened the surviving child away and called the group settled. The root reads `Finishing`, which is what the scheduler documents: own logic done, children still running. The test now asserts that, with the reasoning inline so it doesn't get "fixed" back. Kept: `Source`, `State`, `PermPayload` and the `NodeId` alias in `hive-host-sock::jobs` — shared vocabulary, still used by hivectl.
This commit is contained in:
parent
4ec1c61d52
commit
f707c60f90
10 changed files with 131 additions and 615 deletions
|
|
@ -210,15 +210,9 @@ pub enum HostRequest {
|
|||
/// matrix GUI disabled). Backs `hivectl open` + the federation
|
||||
/// peer-config block (which reads the bare `domain`).
|
||||
Urls,
|
||||
/// Fetch one job-queue DAG by id — the polling surface behind
|
||||
/// `hivectl`'s wait/progress loop. A multi-step op is a single DAG
|
||||
/// (its whole graph in `nodes`). Result: [`HostResponse::dags`].
|
||||
QueueDag { id: u64 },
|
||||
/// Fetch one or more job-queue nodes plus their live subtrees, as
|
||||
/// generic `hive-jobq-wire` nodes — `hivectl`'s wait/progress loop.
|
||||
/// Sibling of [`Self::QueueDag`]: same graph, through the generic
|
||||
/// projection instead of the typed `DagView`/`NodeView` (kept for
|
||||
/// `QueueDag`'s other consumer, `/api/state.rebuild_queue`). No
|
||||
/// generic `hive-jobq-wire` nodes — `hivectl`'s wait/progress loop,
|
||||
/// and the only way the queue is served. No
|
||||
/// assumption that an id names a DAG container or root — whatever
|
||||
/// node has that id, the backend hands back its subtree as-is. A
|
||||
/// batch op that submits several independent roots (e.g. one per
|
||||
|
|
@ -542,23 +536,16 @@ pub struct HostResponse {
|
|||
/// different question".
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub agent_exists: Option<bool>,
|
||||
/// Ids of the job-queue DAGs this request submitted (rebuild /
|
||||
/// Ids of the job-queue roots this request submitted (rebuild /
|
||||
/// restart / power ops). Clients poll them via
|
||||
/// [`HostRequest::QueueDag`]; `None` for non-submitting requests.
|
||||
/// [`HostRequest::QueueNodes`]; `None` for non-submitting requests.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub queued_dags: Option<Vec<u64>>,
|
||||
/// `QueueDag` result — the requested DAG followed by its live
|
||||
/// fan-out children ([`jobs::DagView`]). Empty when the DAG has
|
||||
/// been evicted from the queue's history tail.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub dags: Option<Vec<jobs::DagView>>,
|
||||
/// `QueueNodes` result — the requested nodes plus their live subtrees,
|
||||
/// as generic `hive-jobq-wire` nodes, all roots' subtrees combined in
|
||||
/// one flat list. `None` for every other request kind. An id with no
|
||||
/// live node in the graph is silently dropped rather than erroring
|
||||
/// the whole batch — see `JobQueue::node_subtrees`'s doc comment for
|
||||
/// why a *completed* DAG's nodes don't vanish the same way
|
||||
/// `QueueDag`'s do; callers should read each root node's `state` for
|
||||
/// the whole batch — callers should read each root node's `state` for
|
||||
/// terminality, not absence.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub nodes: Option<Vec<hive_jobq_wire::GraphNode>>,
|
||||
|
|
@ -652,16 +639,6 @@ impl HostResponse {
|
|||
}
|
||||
}
|
||||
|
||||
/// `QueueDag` result — the polled DAG + its live children.
|
||||
#[must_use]
|
||||
pub fn dags(dags: Vec<jobs::DagView>) -> Self {
|
||||
Self {
|
||||
ok: true,
|
||||
dags: Some(dags),
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// `QueueNodes` result — the polled node + its subtree, as generic
|
||||
/// wire nodes.
|
||||
#[must_use]
|
||||
|
|
|
|||
Loading…
Reference in a new issue