hive-c0re/hivectl/hive-agent: pause as a job-queue DAG node (closes #3056)
This commit is contained in:
parent
a92f7351d9
commit
20a7a21053
13 changed files with 316 additions and 27 deletions
|
|
@ -329,24 +329,43 @@ async fn handle_spawn(coord: &Arc<Coordinator>, name: &str) -> Result<HostRespon
|
|||
/// `hivectl pause|resume` / the dashboard toggle: write or remove the
|
||||
/// agent's pause marker.
|
||||
///
|
||||
/// Deliberately not a lifecycle DAG. There's no container operation to
|
||||
/// sequence — it's one marker file, and the harness picks it up on its
|
||||
/// next poll — so queueing it would only add latency and a lease. That
|
||||
/// also means it works on a stopped agent: the marker is sticky, so the
|
||||
/// agent comes up paused.
|
||||
/// **Resume** stays synchronous, direct marker removal — there's
|
||||
/// nothing to acknowledge (a resumed agent just starts driving turns
|
||||
/// again on its own next poll, no handshake needed), and nobody has
|
||||
/// asked resume to wait.
|
||||
///
|
||||
/// **Pause** rides the job queue (`PauseSignal → PauseDrain`, see
|
||||
/// `job_queue::power::pause_many`) instead of writing the marker
|
||||
/// synchronously here: pausing wants the same "confirmed, not just
|
||||
/// requested" signal a graceful stop gets from its `Signal → Drain`
|
||||
/// pair, and the DAG's agent lease is what stops a pause from racing
|
||||
/// an in-flight rebuild/stop of the same agent — a synchronous write
|
||||
/// had no such protection. Still works on a stopped agent (the queued
|
||||
/// `PauseSignal` writes the same sticky marker either way, container
|
||||
/// running or not).
|
||||
async fn handle_set_paused(
|
||||
coord: &std::sync::Arc<Coordinator>,
|
||||
name: &hive_types::Ident,
|
||||
paused: bool,
|
||||
) -> HostResponse {
|
||||
if let Err(e) = Coordinator::set_paused(name, paused).await {
|
||||
return HostResponse::error(format!("set paused={paused} for {name}: {e}"));
|
||||
if !paused {
|
||||
if let Err(e) = Coordinator::set_paused(name, false).await {
|
||||
return HostResponse::error(format!("set paused=false for {name}: {e}"));
|
||||
}
|
||||
tracing::info!(%name, "agent pause marker cleared");
|
||||
// Refresh the dashboard's view so the paused badge flips without
|
||||
// waiting for the next periodic rescan.
|
||||
coord.rescan_containers_and_emit().await;
|
||||
return HostResponse::success();
|
||||
}
|
||||
match crate::job_queue::power::pause_many(coord, std::slice::from_ref(&name.to_string())).await
|
||||
{
|
||||
Ok(ids) => {
|
||||
tracing::info!(%name, "agent pause queued");
|
||||
HostResponse::queued(ids.into_iter().map(hive_jobq::NodeId::get).collect())
|
||||
}
|
||||
Err(e) => HostResponse::error(format!("queue pause for {name}: {e}")),
|
||||
}
|
||||
tracing::info!(%name, paused, "agent pause marker updated");
|
||||
// Refresh the dashboard's view so the paused badge flips without
|
||||
// waiting for the next periodic rescan.
|
||||
coord.rescan_containers_and_emit().await;
|
||||
HostResponse::success()
|
||||
}
|
||||
|
||||
/// Collect per-agent status rows for `hivectl status` and the dashboard.
|
||||
|
|
|
|||
Loading…
Reference in a new issue