use super::GraphNode;
use super::builder::UnifiedGraph;
use anyhow::{Result, bail};
use petgraph::algo::toposort;
use petgraph::visit::Topo;
use std::collections::HashMap;
pub struct Scheduler;
impl Scheduler {
pub fn plan_execution(unified_graph: &UnifiedGraph) -> Result<Vec<GraphNode>> {
match toposort(&unified_graph.graph, None) {
Ok(node_indices) => {
let scheduled_nodes = node_indices
.into_iter()
.map(|idx| unified_graph.graph[idx].clone())
.collect();
Ok(scheduled_nodes)
}
Err(cycle) => {
bail!(
"Cyclic dependency detected in unified build graph around node index {:?}",
cycle.node_id()
);
}
}
}
pub fn plan_wavefronts(unified_graph: &UnifiedGraph) -> Result<Vec<Vec<GraphNode>>> {
let mut depths: HashMap<petgraph::graph::NodeIndex, usize> = HashMap::new();
let mut topo = Topo::new(&unified_graph.graph);
while let Some(node_idx) = topo.next(&unified_graph.graph) {
let max_pred_depth = unified_graph
.graph
.neighbors_directed(node_idx, petgraph::Direction::Incoming)
.map(|pred| depths.get(&pred).copied().unwrap_or(0))
.max();
let current_depth = match max_pred_depth {
Some(depth) => depth + 1,
None => 0,
};
depths.insert(node_idx, current_depth);
}
if depths.len() != unified_graph.graph.node_count() {
bail!("Cyclic dependency detected during wavefront analysis");
}
let max_depth = depths.values().copied().max().unwrap_or(0);
let mut wavefronts = vec![Vec::new(); max_depth + 1];
for (node_idx, depth) in depths {
let node = unified_graph.graph[node_idx].clone();
wavefronts[depth].push(node);
}
Ok(wavefronts)
}
}