Compare commits

...
Author SHA1 Message Date
damocles
e8b24e7021 fix(948): topo-sort cascade agents in meta_update_cascade_agents 2026-06-01 16:50:41 +02:00
damocles
5dc31c1e13 fix(948): make topology_sort pub 2026-06-01 16:50:40 +02:00
2 changed files with 10 additions and 3 deletions

View file

@ -209,7 +209,7 @@ pub async fn ensure_manager(coord: &Arc<Coordinator>) -> Result<()> {
/// Sort `names` in-place so parents precede their children in the topology. /// Sort `names` in-place so parents precede their children in the topology.
/// Uses BFS from root agents (depth 0). Agents absent from `topo` sort last, /// Uses BFS from root agents (depth 0). Agents absent from `topo` sort last,
/// alphabetically within their tier. Stable within each depth tier. /// alphabetically within their tier. Stable within each depth tier.
fn topology_sort(names: &mut Vec<String>, topo: &std::collections::BTreeMap<String, Option<String>>) { pub fn topology_sort(names: &mut Vec<String>, topo: &std::collections::BTreeMap<String, Option<String>>) {
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
// Build depth map using owned clones so the borrow on `names` is released // Build depth map using owned clones so the borrow on `names` is released
// before the sort_by mutable borrow. // before the sort_by mutable borrow.
@ -300,3 +300,4 @@ pub async fn run(coord: Arc<Coordinator>) -> Result<()> {
coord.emit_rebuild_queue_snapshot(); coord.emit_rebuild_queue_snapshot();
Ok(()) Ok(())
} }

View file

@ -648,7 +648,7 @@ pub async fn meta_update_cascade_agents(inputs: &[String]) -> Vec<String> {
.filter_map(|i| i.strip_prefix("agent-")) .filter_map(|i| i.strip_prefix("agent-"))
.map(|rest| rest.split('/').next().unwrap_or(rest).to_owned()) .map(|rest| rest.split('/').next().unwrap_or(rest).to_owned())
.collect(); .collect();
if touched_hyperhive || inputs.is_empty() { let mut names = if touched_hyperhive || inputs.is_empty() {
crate::lifecycle::list() crate::lifecycle::list()
.await .await
.unwrap_or_default() .unwrap_or_default()
@ -664,7 +664,12 @@ pub async fn meta_update_cascade_agents(inputs: &[String]) -> Vec<String> {
.collect() .collect()
} else { } else {
touched_agents touched_agents
} };
// Sort parents before children so the sequential queue worker
// always rebuilds a parent before any of its dependents.
let topo = crate::topology::read();
crate::auto_update::topology_sort(&mut names, &topo);
names
} }
/// Current unix timestamp in seconds. `now()` calls are pulled into a /// Current unix timestamp in seconds. `now()` calls are pulled into a
@ -1164,3 +1169,4 @@ mod tests {
); );
} }
} }