use indexmap::{IndexMap, IndexSet};
pub fn compute_evaluation_batches(
sorted: &IndexSet<String>,
graph: &IndexMap<String, IndexSet<String>>,
table_paths: &IndexSet<String>,
) -> Vec<Vec<String>> {
let mut batches: Vec<Vec<String>> = Vec::new();
let mut node_to_batch: IndexMap<String, usize> = IndexMap::new();
for node in sorted {
let deps = graph.get(node);
let max_dep_batch = if let Some(deps) = deps {
deps.iter()
.filter_map(|dep| {
if sorted.contains(dep) {
return node_to_batch.get(dep).copied();
}
if dep.contains("/$table/") {
for table_path in table_paths {
if dep.starts_with(table_path) {
return node_to_batch.get(table_path).copied();
}
}
}
if dep.contains("/$datas/")
|| dep.ends_with("/$skip")
|| dep.ends_with("/$clear")
{
for table_path in table_paths {
if dep.starts_with(table_path) {
return node_to_batch.get(table_path).copied();
}
}
}
None
})
.max()
} else {
None
};
let batch_idx = max_dep_batch.map(|b| b + 1).unwrap_or(0);
while batches.len() <= batch_idx {
batches.push(Vec::new());
}
batches[batch_idx].push(node.clone());
node_to_batch.insert(node.clone(), batch_idx);
}
batches
}
pub fn collect_transitive_deps(
deps: &IndexSet<String>,
graph: &IndexMap<String, IndexSet<String>>,
table_paths: &IndexSet<String>,
result: &mut IndexSet<String>,
) {
for dep in deps {
if table_paths.contains(dep) {
continue;
}
if result.insert(dep.clone()) {
if let Some(sub_deps) = graph.get(dep) {
collect_transitive_deps(sub_deps, graph, table_paths, result);
}
}
}
}