1use contextdb_core::{AdjEntry, EdgeType, NodeId};
2use parking_lot::RwLock;
3use std::collections::HashMap;
4
5pub struct GraphStore {
6 pub forward_adj: RwLock<HashMap<NodeId, Vec<AdjEntry>>>,
7 pub reverse_adj: RwLock<HashMap<NodeId, Vec<AdjEntry>>>,
8}
9
10impl Default for GraphStore {
11 fn default() -> Self {
12 Self::new()
13 }
14}
15
16impl GraphStore {
17 pub fn new() -> Self {
18 Self {
19 forward_adj: RwLock::new(HashMap::new()),
20 reverse_adj: RwLock::new(HashMap::new()),
21 }
22 }
23
24 pub fn apply_inserts(&self, inserts: Vec<AdjEntry>) {
25 let mut fwd = self.forward_adj.write();
26 let mut rev = self.reverse_adj.write();
27
28 for entry in inserts {
29 rev.entry(entry.target).or_default().push(entry.clone());
30 fwd.entry(entry.source).or_default().push(entry);
31 }
32 }
33
34 pub fn apply_deletes(&self, deletes: Vec<(NodeId, EdgeType, NodeId, u64)>) {
35 let mut fwd = self.forward_adj.write();
36 let mut rev = self.reverse_adj.write();
37
38 for (source, edge_type, target, deleted_tx) in deletes {
39 if let Some(entries) = fwd.get_mut(&source) {
40 for e in entries.iter_mut() {
41 if e.target == target && e.edge_type == edge_type && e.deleted_tx.is_none() {
42 e.deleted_tx = Some(deleted_tx);
43 }
44 }
45 }
46
47 if let Some(entries) = rev.get_mut(&target) {
48 for e in entries.iter_mut() {
49 if e.source == source && e.edge_type == edge_type && e.deleted_tx.is_none() {
50 e.deleted_tx = Some(deleted_tx);
51 }
52 }
53 }
54 }
55 }
56
57 pub fn insert_loaded_edge(&self, entry: AdjEntry) {
58 let mut fwd = self.forward_adj.write();
59 let mut rev = self.reverse_adj.write();
60 rev.entry(entry.target).or_default().push(entry.clone());
61 fwd.entry(entry.source).or_default().push(entry);
62 }
63}