use petgraph::stable_graph::{EdgeIndex, NodeIndex};
use crate::channels::ComponentEvent;
use super::graph::ComponentGraph;
use super::{ComponentNode, RelationshipKind};
pub struct GraphTransaction<'g> {
graph: &'g mut ComponentGraph,
added_nodes: Vec<(NodeIndex, String)>,
added_edges: Vec<EdgeIndex>,
pending_events: Vec<ComponentEvent>,
committed: bool,
}
impl<'g> GraphTransaction<'g> {
pub(super) fn new(graph: &'g mut ComponentGraph) -> Self {
Self {
graph,
added_nodes: Vec::new(),
added_edges: Vec::new(),
pending_events: Vec::new(),
committed: false,
}
}
pub fn add_component(&mut self, node: ComponentNode) -> anyhow::Result<NodeIndex> {
let id = node.id.clone();
let (node_idx, event, owns_edge, owned_by_edge) =
self.graph.add_component_internal(node)?;
self.added_nodes.push((node_idx, id));
self.added_edges.push(owns_edge);
self.added_edges.push(owned_by_edge);
if let Some(event) = event {
self.pending_events.push(event);
}
Ok(node_idx)
}
pub fn add_relationship(
&mut self,
from_id: &str,
to_id: &str,
forward: RelationshipKind,
) -> anyhow::Result<()> {
let (fwd, rev) = self
.graph
.add_relationship_internal(from_id, to_id, forward)?;
if let Some(e) = fwd {
self.added_edges.push(e);
}
if let Some(e) = rev {
self.added_edges.push(e);
}
Ok(())
}
pub fn commit(mut self) {
self.committed = true;
for event in &self.pending_events {
let _ = self.graph.event_tx.send(event.clone());
self.graph.event_history.record_event(event.clone());
}
}
}
impl<'g> Drop for GraphTransaction<'g> {
fn drop(&mut self) {
if self.committed {
return;
}
for &edge_idx in self.added_edges.iter().rev() {
self.graph.graph.remove_edge(edge_idx);
}
for (node_idx, ref id) in self.added_nodes.iter().rev() {
self.graph.index.remove(id.as_str());
self.graph.graph.remove_node(*node_idx);
}
}
}