lifecycle: only prebuild when there's downtime to shave (mara on #721)

This commit is contained in:
damocles 2026-05-31 11:54:33 +02:00 committed by Mara
commit 0a98327685

View file

@ -425,22 +425,25 @@ pub async fn rebuild_no_meta(
// the new profile and the new EXTRA_NSPAWN_FLAGS in one go.
// If the container was already stopped, `update` builds + sets
// the profile and we leave it stopped.
//
// Pre-build the system toplevel **before** stopping the
// container so the container is only down for the
// profile-swap + restart, not for the full nix evaluation +
// fetch + build cycle (#706). Failure here aborts before we
// touch the running container — the agent keeps serving its
// previous generation while the operator looks at the eval
// error. `nixos-container update` then finds the toplevel
// already in the store and skips straight to the profile
// swap.
let was_running = is_running(name).await;
prebuild_toplevel(name, &flake_ref).await?;
set_nspawn_flags(&container, agent_dir, claude_dir, notes_dir)?;
set_resource_limits(&container)?;
systemd_daemon_reload().await?;
if was_running {
// Pre-build the system toplevel **before** stopping the
// running container so the agent keeps serving its
// previous generation while the eval + fetch + build
// happens out-of-band (#706). `nixos-container update`
// then finds the toplevel cached and skips straight to
// the profile-swap + restart — downtime collapses to that
// window only. Build failures surface here, before we
// touch the container.
//
// When the container is already stopped there's no
// downtime to shave (mara on #721#9007) — let `update`
// do the build inline rather than evaluating the flake
// twice for nothing.
prebuild_toplevel(name, &flake_ref).await?;
run(&["stop", &container]).await?;
}
run(&["update", &container, "--flake", &flake_ref]).await?;
@ -450,12 +453,11 @@ pub async fn rebuild_no_meta(
Ok(())
}
} else {
// First spawn: pre-build for parity (`nixos-container create`
// builds + creates the container, so warming the store first
// doesn't shave downtime — there's none to shave — but it
// surfaces eval / fetch errors before `create` half-spawns a
// container record that the operator then has to clean up).
prebuild_toplevel(name, &flake_ref).await?;
// First spawn: no running container, no downtime to shave.
// `nixos-container create` builds + creates atomically — if
// the build fails, no container record is left around to
// clean up — so a pre-build adds nothing but a duplicate
// eval (mara on #721#9007).
run(&["create", &container, "--flake", &flake_ref]).await?;
set_nspawn_flags(&container, agent_dir, claude_dir, notes_dir)?;
set_resource_limits(&container)?;