docs(#2627): add READMEs for hive-jobq + the socket wire crates
Adds crate READMEs (matching the hive-claude precedent) and wires readme = "README.md" into each Cargo.toml [package] for hive-jobq, hive-host-sock, and hive-priv-sock — the crates squarely in the infra lane. Each README leads with purpose + when-to-use and points at the crate-root //! docs for depth rather than duplicating them. First increment of the per-crate-README effort; the shape here is the proposed template for the remaining crates (see issue discussion).
This commit is contained in:
parent
e9df5def02
commit
4017a57350
6 changed files with 106 additions and 0 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
name = "hive-host-sock"
|
name = "hive-host-sock"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
24
hive-host-sock/README.md
Normal file
24
hive-host-sock/README.md
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
# hive-host-sock
|
||||||
|
|
||||||
|
Wire types for the **host admin socket** (`/run/hyperhive/host.sock`) — the
|
||||||
|
host-control protocol spoken between the `hivectl` operator CLI and the
|
||||||
|
`hive-c0re` daemon.
|
||||||
|
|
||||||
|
## Why it's its own crate
|
||||||
|
|
||||||
|
Re-homed out of `hive-sh4re` so a standalone `hivectl` depends on **just this
|
||||||
|
protocol crate** instead of the whole daemon-shared crate. `hivectl` drives the
|
||||||
|
full hive (spawn / kill / destroy / rebuild / deploy) over this socket without
|
||||||
|
linking `hive-c0re`; keeping the request/response shapes here is what makes that
|
||||||
|
thin dependency possible.
|
||||||
|
|
||||||
|
## Shape
|
||||||
|
|
||||||
|
Serde-derived request/response enums for the host admin protocol. The larger
|
||||||
|
shared payload types some variants reference (`Approval`, `AgentStatusRow`,
|
||||||
|
`jobs::DagView`) stay in `hive-sh4re` — this crate is only the protocol
|
||||||
|
envelope, no server or client implementation.
|
||||||
|
|
||||||
|
See `docs/boundary.md` (host admin socket access) for the trust model around who
|
||||||
|
may connect to the socket, and `hive-priv-sock` for the sibling split on the
|
||||||
|
privileged-helper socket.
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
name = "hive-jobq"
|
name = "hive-jobq"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
58
hive-jobq/README.md
Normal file
58
hive-jobq/README.md
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
# hive-jobq
|
||||||
|
|
||||||
|
A persistent job-DAG scheduler, extracted from hive-c0re's in-tree `job_queue`
|
||||||
|
as a **domain-agnostic** library. It schedules a single persistent graph of
|
||||||
|
nodes over named resources; it knows nothing about containers, rebuilds, or any
|
||||||
|
hyperhive type — the node payload `N` and resource name `R` are both generic, so
|
||||||
|
the caller supplies its own domain.
|
||||||
|
|
||||||
|
## When to use it
|
||||||
|
|
||||||
|
Reach for this crate whenever you need to run a DAG of interdependent work items
|
||||||
|
under bounded, named concurrency — the hive-c0re rebuild/lifecycle queue is the
|
||||||
|
first consumer, but nothing here is specific to it. The caller defines the node
|
||||||
|
kinds, wires deps, and supplies a runner; the scheduler decides what can start.
|
||||||
|
|
||||||
|
## Model
|
||||||
|
|
||||||
|
One **persistent graph** for the whole system, not a DAG per job. Enqueuing
|
||||||
|
inserts a self-contained sub-DAG and returns the new node ids; the scheduler
|
||||||
|
runs a continuous loop, starting every node whose deps are satisfied:
|
||||||
|
|
||||||
|
- **Resource deps** are named counting semaphores over a caller-chosen type `R`
|
||||||
|
— e.g. `build-slot` (capacity N), `agent/<name>` (capacity 1), or any
|
||||||
|
unconfigured name (capacity 1, created on use). A node acquires *all* its
|
||||||
|
resource deps atomically at start (all-or-nothing) — no hold-and-wait, so no
|
||||||
|
deadlock.
|
||||||
|
- **Node deps** wait on another node per `DepWhen`: `AfterOk` needs success (a
|
||||||
|
failed dep cancels the dependent), `AfterAny` only needs terminal.
|
||||||
|
|
||||||
|
A node carries two independent axes: its `Dep`s (ordering + resource needs) and
|
||||||
|
its `parent` (structural grouping). The **parent chain**, not the node edges, is
|
||||||
|
what the scheduler consults for resource re-entrancy: a resource unit is held
|
||||||
|
for the acquiring node *plus its whole parent subtree*, and a descendant needing
|
||||||
|
a resource an ancestor already holds re-uses that grant (a re-entrant borrow,
|
||||||
|
one branch at a time) rather than taking a fresh unit.
|
||||||
|
|
||||||
|
A `NodeId` is opaque, stable, and monotonic (safe to persist). The scheduler is
|
||||||
|
single-threaded — it owns the resource table and mutates it directly.
|
||||||
|
|
||||||
|
## Shape
|
||||||
|
|
||||||
|
- **`Graph<N, R>`** — the persistent node store. `insert` mints ids and
|
||||||
|
validates dep/parent references; `set_state` is the single state-transition
|
||||||
|
choke point (and where each node's lifecycle timestamps —
|
||||||
|
`started_at` / `finished_at`, `DateTime<Utc>` — are stamped).
|
||||||
|
- **`Node<N, R>`** — `{ id, parent, payload, deps, state, started_at,
|
||||||
|
finished_at, error }`. All fields public; derives serde for persistence + the
|
||||||
|
wire.
|
||||||
|
- **`Scheduler<N, R>`** — drives the graph: `settle()` starts every ready node
|
||||||
|
(acquiring resources atomically), `complete(id, outcome)` reports a finished
|
||||||
|
node's result and rolls terminality up the parent chain, releasing grants once
|
||||||
|
a subtree is done. `Outcome::{Done, Failed(String)}` — the failure reason
|
||||||
|
rides `Failed` onto the node's `error`.
|
||||||
|
- **`ResourceTable<R>`** — per-name capacities; unconfigured names default to
|
||||||
|
capacity 1.
|
||||||
|
|
||||||
|
See the crate-root and `scheduler` module `//!` docs for the full borrow/release
|
||||||
|
model.
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
name = "hive-priv-sock"
|
name = "hive-priv-sock"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
21
hive-priv-sock/README.md
Normal file
21
hive-priv-sock/README.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# hive-priv-sock
|
||||||
|
|
||||||
|
Wire types for the **`hive-priv` privileged-helper socket**
|
||||||
|
(`/run/hive/priv.sock`) — the contract between `hive-priv` (the root helper,
|
||||||
|
server) and `hive-c0re` (client, via its `priv_client`).
|
||||||
|
|
||||||
|
## Why it's its own crate
|
||||||
|
|
||||||
|
Split out of `hive-sh4re` so `hive-priv` — a **root-privileged** binary —
|
||||||
|
depends on just this narrow protocol crate instead of the much larger
|
||||||
|
daemon-shared crate. Two wins: fewer dependencies in a root process's supply
|
||||||
|
chain, and a small, self-contained interface makes the privilege boundary this
|
||||||
|
crate encodes easier to audit. Mirrors `hive-host-sock`'s split for the host
|
||||||
|
admin socket.
|
||||||
|
|
||||||
|
## Shape
|
||||||
|
|
||||||
|
Serde-derived request/response types only — no server or client logic. Both
|
||||||
|
sides import them so the shapes stay in sync. See `docs/boundary.md` +
|
||||||
|
`docs/security.md` for the privilege boundary these types sit on, and
|
||||||
|
`hive-priv/README` for the helper itself.
|
||||||
Loading…
Reference in a new issue