71 lines
2.7 KiB
Rust
71 lines
2.7 KiB
Rust
//! `hivectl stop` / `start` / `restart` — hive-wide + scoped container
|
|
//! lifecycle. Each verb makes one daemon call and renders the queued DAGs.
|
|
|
|
use std::path::Path;
|
|
|
|
use anyhow::{Context as _, Result};
|
|
|
|
use crate::dag_progress::wait_for_nodes;
|
|
use crate::util::render_lifecycle;
|
|
|
|
pub(crate) async fn stop(
|
|
socket: &Path,
|
|
scope: hive_host_sock::LifecycleScope,
|
|
graceful: bool,
|
|
no_wait: bool,
|
|
) -> Result<()> {
|
|
let resp = crate::client::request(
|
|
socket,
|
|
hive_host_sock::HostRequest::Stop { scope, graceful },
|
|
)
|
|
.await
|
|
.with_context(|| format!("connect to daemon socket {}", socket.display()))?;
|
|
// Render first, but even when an infra failure makes it bail,
|
|
// watch the already-queued agent DAGs before surfacing the error —
|
|
// they run regardless.
|
|
let rendered = render_lifecycle(&resp, "stop queued");
|
|
wait_for_nodes(socket, resp.queued_dags.unwrap_or_default(), no_wait).await?;
|
|
rendered
|
|
}
|
|
|
|
pub(crate) async fn start(
|
|
socket: &Path,
|
|
scope: hive_host_sock::LifecycleScope,
|
|
no_wait: bool,
|
|
) -> Result<()> {
|
|
let resp = crate::client::request(socket, hive_host_sock::HostRequest::Start { scope })
|
|
.await
|
|
.with_context(|| format!("connect to daemon socket {}", socket.display()))?;
|
|
let rendered = render_lifecycle(&resp, "start queued");
|
|
wait_for_nodes(socket, resp.queued_dags.unwrap_or_default(), no_wait).await?;
|
|
rendered
|
|
}
|
|
|
|
/// Restart — one `RestartScoped` daemon call, server-side DAG-based (see
|
|
/// issue tracker "dagify hivectl commands"). Each targeted agent rides
|
|
/// exactly one atomic DAG queued up front — `Restart` (mechanical stop +
|
|
/// reconcile), or `GracefulRestart` with `--graceful` (signal → drain →
|
|
/// mechanical stop → reconcile); infra containers restart synchronously.
|
|
/// No "submit one DAG, wait for it, submit another" composition on either
|
|
/// side of the wire: unlike the old client-side stop-then-start compose, a
|
|
/// dropped `hivectl` connection mid-restart no longer leaves an agent
|
|
/// stopped with no automatic follow-up — the daemon owns the whole
|
|
/// sequence once this call is made.
|
|
///
|
|
/// No `--no-wait` here on purpose, same as before: the operator wants to
|
|
/// see the restart actually land, not just get queued.
|
|
pub(crate) async fn restart(
|
|
socket: &Path,
|
|
scope: hive_host_sock::LifecycleScope,
|
|
graceful: bool,
|
|
) -> Result<()> {
|
|
let resp = crate::client::request(
|
|
socket,
|
|
hive_host_sock::HostRequest::RestartScoped { scope, graceful },
|
|
)
|
|
.await
|
|
.with_context(|| format!("connect to daemon socket {}", socket.display()))?;
|
|
let rendered = render_lifecycle(&resp, "restart queued");
|
|
wait_for_nodes(socket, resp.queued_dags.unwrap_or_default(), false).await?;
|
|
rendered
|
|
}
|