lifecycle: thread on_step callback through rebuild for accurate queue step labels
This commit is contained in:
parent
4df65deb20
commit
d14df8b9a0
4 changed files with 20 additions and 3 deletions
|
|
@ -559,14 +559,17 @@ async fn run_apply_commit(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
coord.set_queue_step(queue_entry_id, "nixos-container update");
|
|
||||||
// Container-level rebuild (or first-time create) against meta#<name>.
|
// Container-level rebuild (or first-time create) against meta#<name>.
|
||||||
|
// Step labels are emitted inside rebuild_no_meta via the callback so
|
||||||
|
// the dashboard reflects actual phase progress rather than a static
|
||||||
|
// "nixos-container update" label for the whole multi-minute window.
|
||||||
let build_result = lifecycle::rebuild_no_meta(
|
let build_result = lifecycle::rebuild_no_meta(
|
||||||
&approval.agent,
|
&approval.agent,
|
||||||
agent_dir,
|
agent_dir,
|
||||||
applied_dir,
|
applied_dir,
|
||||||
claude_dir,
|
claude_dir,
|
||||||
notes_dir,
|
notes_dir,
|
||||||
|
&|step| coord.set_queue_step(queue_entry_id, step),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,6 @@ pub async fn rebuild_agent(
|
||||||
// lifecycle_action; this catches the auto-update scan + any
|
// lifecycle_action; this catches the auto-update scan + any
|
||||||
// other direct caller.
|
// other direct caller.
|
||||||
let guard = coord.transient_guard(name, crate::coordinator::TransientKind::Rebuilding);
|
let guard = coord.transient_guard(name, crate::coordinator::TransientKind::Rebuilding);
|
||||||
coord.set_queue_step(queue_entry_id, "nixos-container update");
|
|
||||||
let result = lifecycle::rebuild(
|
let result = lifecycle::rebuild(
|
||||||
name,
|
name,
|
||||||
&coord.hyperhive_flake,
|
&coord.hyperhive_flake,
|
||||||
|
|
@ -97,6 +96,7 @@ pub async fn rebuild_agent(
|
||||||
coord.dashboard_port,
|
coord.dashboard_port,
|
||||||
&coord.operator_pronouns,
|
&coord.operator_pronouns,
|
||||||
&coord.context_window_tokens,
|
&coord.context_window_tokens,
|
||||||
|
&|step| coord.set_queue_step(queue_entry_id, step),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
drop(guard);
|
drop(guard);
|
||||||
|
|
|
||||||
|
|
@ -354,6 +354,7 @@ pub async fn rebuild(
|
||||||
dashboard_port: u16,
|
dashboard_port: u16,
|
||||||
operator_pronouns: &str,
|
operator_pronouns: &str,
|
||||||
context_window_tokens: &std::collections::HashMap<String, u64>,
|
context_window_tokens: &std::collections::HashMap<String, u64>,
|
||||||
|
on_step: &(dyn Fn(&str) + Send + Sync),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Sync the meta flake (idempotent — no-op when the rendered
|
// Sync the meta flake (idempotent — no-op when the rendered
|
||||||
// flake matches disk) so a manual rebuild from the dashboard
|
// flake matches disk) so a manual rebuild from the dashboard
|
||||||
|
|
@ -373,7 +374,7 @@ pub async fn rebuild(
|
||||||
// `applied/<n>/main` currently points at (deployed/<latest>).
|
// `applied/<n>/main` currently points at (deployed/<latest>).
|
||||||
// Commits the lock if it changed.
|
// Commits the lock if it changed.
|
||||||
crate::meta::lock_update_for_rebuild(name).await?;
|
crate::meta::lock_update_for_rebuild(name).await?;
|
||||||
rebuild_no_meta(name, agent_dir, applied_dir, claude_dir, notes_dir).await
|
rebuild_no_meta(name, agent_dir, applied_dir, claude_dir, notes_dir, on_step).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Container-level rebuild without touching the meta repo. Callers
|
/// Container-level rebuild without touching the meta repo. Callers
|
||||||
|
|
@ -381,12 +382,18 @@ pub async fn rebuild(
|
||||||
/// drives meta through the two-phase prepare/finalize/abort flow)
|
/// drives meta through the two-phase prepare/finalize/abort flow)
|
||||||
/// use this directly. Public `rebuild` wraps it with idempotent meta
|
/// use this directly. Public `rebuild` wraps it with idempotent meta
|
||||||
/// sync + lock-bump-and-commit.
|
/// sync + lock-bump-and-commit.
|
||||||
|
///
|
||||||
|
/// `on_step` is called at each phase boundary with a short human-readable
|
||||||
|
/// label so callers can surface progress (e.g. update the rebuild-queue
|
||||||
|
/// step shown in the dashboard). Pass `&|_| ()` when progress reporting
|
||||||
|
/// is not needed.
|
||||||
pub async fn rebuild_no_meta(
|
pub async fn rebuild_no_meta(
|
||||||
name: &str,
|
name: &str,
|
||||||
agent_dir: &Path,
|
agent_dir: &Path,
|
||||||
applied_dir: &Path,
|
applied_dir: &Path,
|
||||||
claude_dir: &Path,
|
claude_dir: &Path,
|
||||||
notes_dir: &Path,
|
notes_dir: &Path,
|
||||||
|
on_step: &(dyn Fn(&str) + Send + Sync),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
validate(name)?;
|
validate(name)?;
|
||||||
if let Some(other) = port_collision(name).await {
|
if let Some(other) = port_collision(name).await {
|
||||||
|
|
@ -433,9 +440,12 @@ pub async fn rebuild_no_meta(
|
||||||
// When the container is already stopped there's no
|
// When the container is already stopped there's no
|
||||||
// downtime to shave — let `update` do the build inline
|
// downtime to shave — let `update` do the build inline
|
||||||
// rather than evaluating the flake twice for nothing.
|
// rather than evaluating the flake twice for nothing.
|
||||||
|
on_step("nix build");
|
||||||
prebuild_toplevel(name, &flake_ref).await?;
|
prebuild_toplevel(name, &flake_ref).await?;
|
||||||
|
on_step("nixos-container stop");
|
||||||
run(&["stop", &container]).await?;
|
run(&["stop", &container]).await?;
|
||||||
}
|
}
|
||||||
|
on_step("nixos-container update");
|
||||||
run(&["update", &container, "--flake", &flake_ref]).await?;
|
run(&["update", &container, "--flake", &flake_ref]).await?;
|
||||||
if was_running {
|
if was_running {
|
||||||
// Normal path: start into the new generation. The activation
|
// Normal path: start into the new generation. The activation
|
||||||
|
|
@ -450,6 +460,7 @@ pub async fn rebuild_no_meta(
|
||||||
// `stop` requests a graceful SIGTERM drain; `kill` then SIGKILLs
|
// `stop` requests a graceful SIGTERM drain; `kill` then SIGKILLs
|
||||||
// any lingering processes so the next `start` enters a clean state
|
// any lingering processes so the next `start` enters a clean state
|
||||||
// without a generation transition, letting the activation succeed.
|
// without a generation transition, letting the activation succeed.
|
||||||
|
on_step("nixos-container start");
|
||||||
if let Err(start_err) = run(&["start", &container]).await {
|
if let Err(start_err) = run(&["start", &container]).await {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
container = %container,
|
container = %container,
|
||||||
|
|
@ -488,10 +499,12 @@ pub async fn rebuild_no_meta(
|
||||||
// the build fails, no container record is left around to
|
// the build fails, no container record is left around to
|
||||||
// clean up — so a pre-build adds nothing but a duplicate
|
// clean up — so a pre-build adds nothing but a duplicate
|
||||||
// eval.
|
// eval.
|
||||||
|
on_step("nixos-container create");
|
||||||
run(&["create", &container, "--flake", &flake_ref]).await?;
|
run(&["create", &container, "--flake", &flake_ref]).await?;
|
||||||
set_nspawn_flags(&container, agent_dir, claude_dir, notes_dir)?;
|
set_nspawn_flags(&container, agent_dir, claude_dir, notes_dir)?;
|
||||||
set_resource_limits(&container)?;
|
set_resource_limits(&container)?;
|
||||||
systemd_daemon_reload().await?;
|
systemd_daemon_reload().await?;
|
||||||
|
on_step("nixos-container start");
|
||||||
run(&["start", &container]).await
|
run(&["start", &container]).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@ async fn dispatch(req: &HostRequest, coord: Arc<Coordinator>) -> HostResponse {
|
||||||
coord.dashboard_port,
|
coord.dashboard_port,
|
||||||
&coord.operator_pronouns,
|
&coord.operator_pronouns,
|
||||||
&coord.context_window_tokens,
|
&coord.context_window_tokens,
|
||||||
|
&|_| (),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
// Mirror auto_update::rebuild_agent — the manager wants
|
// Mirror auto_update::rebuild_agent — the manager wants
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue