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.
69 lines
2.6 KiB
Rust
69 lines
2.6 KiB
Rust
//! Vocabulary hive-c0re's job queue shares with its clients: where a job
|
|
//! came from ([`Source`]), what a permission change carries
|
|
//! ([`PermPayload`]), and the scheduler's lifecycle [`State`].
|
|
//!
|
|
//! **The typed `DagView`/`NodeView` projection that used to live here is
|
|
//! gone.** One graph is served one way now — `hive_jobq_wire`'s generic
|
|
//! `GraphNode`, over the `QueueNodes` socket request and
|
|
//! `GET /api/jobq/graph` — so there is no second shape to keep in
|
|
//! agreement with the first. Queue internals (node kinds, edges,
|
|
//! scheduling) live in `hive-c0re::job_queue`.
|
|
//! Semantics: `docs/coordinator.md::Job queue`.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// Where the submit request originated — drives the "why" chip on the
|
|
/// dashboard.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum Source {
|
|
/// Operator action (dashboard button, CLI, manager tool).
|
|
Manual,
|
|
/// Meta-update cascade rebuild (grown into the meta-update DAG).
|
|
MetaUpdate,
|
|
/// Boot-time submission (the boot sweep DAG + boot reconciles).
|
|
AutoUpdate,
|
|
/// Crash recovery path (future use).
|
|
CrashRecover,
|
|
/// Operator approved a pending `Approval` row; `approval_id` on
|
|
/// the DAG points back at the source row.
|
|
Approval,
|
|
}
|
|
|
|
impl Source {
|
|
#[must_use]
|
|
pub fn as_str(self) -> &'static str {
|
|
match self {
|
|
Source::Manual => "manual",
|
|
Source::MetaUpdate => "meta_update",
|
|
Source::AutoUpdate => "auto_update",
|
|
Source::CrashRecover => "crash_recover",
|
|
Source::Approval => "approval",
|
|
}
|
|
}
|
|
}
|
|
|
|
pub use hive_jobq::State;
|
|
|
|
/// Kind-specific payload for `Template::PermChange` DAGs.
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum PermPayload {
|
|
/// Set the tool groups for one agent (`tool-groups.json`).
|
|
ToolGroups { groups: Vec<String> },
|
|
/// Set the capabilities for one agent (`capabilities.json`).
|
|
Capabilities { caps: Vec<String> },
|
|
/// Set both perm-types in one entry — the batch
|
|
/// `POST /api/permissions` path. `None` leaves that file untouched;
|
|
/// present fields commit together and rebuild once.
|
|
Combined {
|
|
groups: Option<Vec<String>>,
|
|
caps: Option<Vec<String>>,
|
|
},
|
|
}
|
|
|
|
/// Node id. Carries the scheduler crate's globally-monotonic node id
|
|
/// (`hive_jobq::NodeId`) verbatim on the wire — unique across all DAGs, not
|
|
/// just within one. Consumers treat it opaquely (grouping + dep matching),
|
|
/// so the widening from the old dag-local `u32` is transparent.
|
|
pub type NodeId = u64;
|