use super::topology;
use crate::graph::v2::{GraphNodeId, GraphSnapshot};
use std::collections::{BTreeMap, BTreeSet, VecDeque};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GraphBlastRadius {
pub seeds: Vec<GraphNodeId>,
pub impacted: Vec<GraphNodeId>,
}
pub fn blast_radius(snapshot: &GraphSnapshot, seeds: &[GraphNodeId]) -> GraphBlastRadius {
let topology = topology(snapshot);
let present_seeds = seeds
.iter()
.filter(|seed| topology.node_set.contains(seed))
.cloned()
.collect::<BTreeSet<_>>();
let mut visited = present_seeds.clone();
let mut queue = present_seeds.iter().cloned().collect::<VecDeque<_>>();
while let Some(node) = queue.pop_front() {
for dependent in &topology.incoming[&node] {
if visited.insert(dependent.clone()) {
queue.push_back(dependent.clone());
}
}
}
let impacted = visited
.into_iter()
.filter(|node| !present_seeds.contains(node))
.collect::<Vec<_>>();
GraphBlastRadius {
seeds: present_seeds.into_iter().collect(),
impacted,
}
}
pub fn direct_dependents(snapshot: &GraphSnapshot) -> BTreeMap<GraphNodeId, BTreeSet<GraphNodeId>> {
let topology = topology(snapshot);
let mut dependents = topology
.node_ids
.iter()
.cloned()
.map(|id| (id, BTreeSet::new()))
.collect::<BTreeMap<GraphNodeId, BTreeSet<GraphNodeId>>>();
for edge in &topology.edges {
if edge.kind.is_dependency() {
dependents
.get_mut(&edge.to)
.expect("validated target node")
.insert(edge.from.clone());
}
}
dependents
}