From 5857f1f8716194598723373c74a193af1df58bf6 Mon Sep 17 00:00:00 2001 From: damocles Date: Mon, 13 Jul 2026 17:13:11 +0200 Subject: [PATCH] feat(#2008): rebuild running agents first in the startup sweep --- hive-c0re/src/workers/auto_update.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/hive-c0re/src/workers/auto_update.rs b/hive-c0re/src/workers/auto_update.rs index 09a1bc55..9ccc19a6 100644 --- a/hive-c0re/src/workers/auto_update.rs +++ b/hive-c0re/src/workers/auto_update.rs @@ -226,7 +226,9 @@ pub async fn run(coord: Arc) -> Result<()> { // agent without an `agent_power` row is seeded from its observed // state (running ⇒ Up), after which the DB is authoritative. let mut any_stale = false; - let mut fanout: Vec = Vec::new(); // stale ∧ wanted=Up → sweep rebuild + // stale ∧ wanted=Up → sweep rebuild. The bool is the agent's observed + // running state, used to order running agents first before submit. + let mut fanout: Vec<(String, bool)> = Vec::new(); let mut drifted: Vec = Vec::new(); // fresh ∧ wanted≠observed → reconcile let mut n_deferred = 0usize; let mut n_skipped = 0usize; @@ -251,7 +253,7 @@ pub async fn run(coord: Arc) -> Result<()> { // Rebuild against the post-bump lock; the DAG's tail // Reconcile brings the agent (back) up — covering both // the running-stale and stopped-but-wanted-up cases. - fanout.push(name.clone()); + fanout.push((name.clone(), running)); continue; } // Stale but wanted offline: no boot-time nix work — the @@ -273,6 +275,15 @@ pub async fn run(coord: Arc) -> Result<()> { "boot reconcile" ); + // Rebuild running agents first. All fanout entries are wanted=Up; + // among them, warm the live/serving agents onto the fresh config before the + // stopped-but-wanted-up ones so the scarce build slots hit uptime-critical + // agents first. Stable sort keeps topology order (parents before children) + // within each running/stopped group. The `drifted` reconciles aren't sorted + // — they hold no build slot and run concurrently, so their order is moot. + fanout.sort_by_key(|(_, running)| !running); + let fanout: Vec = fanout.into_iter().map(|(name, _)| name).collect(); + submit_boot_tree(&coord, any_stale, fanout, drifted, n_deferred, n_skipped); Ok(()) }