pub struct MaterializedGraph {
pub nodes: HashMap<String, Node>,
pub edges: HashMap<String, Edge>,
pub outgoing: HashMap<String, HashSet<String>>,
pub incoming: HashMap<String, HashSet<String>>,
pub by_type: HashMap<String, HashSet<String>>,
pub ontology: Ontology,
pub quarantined: HashSet<Hash>,
}Expand description
Materialized graph — derived from the op log.
Provides fast queries without replaying the full log. Updated incrementally as new entries arrive, or rebuilt from scratch by replaying the entire op log.
CRDT semantics:
- Add-wins for topology (concurrent add + remove → node/edge exists)
- LWW (Last-Writer-Wins) per property key (highest Lamport clock wins)
- Tombstones for deletes (mark as deleted, don’t physically remove)
Fields§
§nodes: HashMap<String, Node>node_id → Node
edges: HashMap<String, Edge>edge_id → Edge
outgoing: HashMap<String, HashSet<String>>node_id → set of outgoing edge_ids
incoming: HashMap<String, HashSet<String>>node_id → set of incoming edge_ids
by_type: HashMap<String, HashSet<String>>node_type → set of node_ids (type index)
ontology: OntologyThe ontology (for validation during materialization)
quarantined: HashSet<Hash>R-02: entries that failed ontology validation during apply(). These entries exist in the oplog (for CRDT convergence) but are invisible in the materialized graph. Grow-only set — monotonic, safe.
Implementations§
Source§impl MaterializedGraph
impl MaterializedGraph
Sourcepub fn new(ontology: Ontology) -> Self
pub fn new(ontology: Ontology) -> Self
Create an empty materialized graph with the given ontology.
Sourcepub fn apply(&mut self, entry: &Entry)
pub fn apply(&mut self, entry: &Entry)
Apply a single entry to the graph (incremental materialization).
R-02: Validates AddNode/AddEdge payloads against the ontology.
Invalid entries are quarantined (added to self.quarantined) and
skipped for materialization. They remain in the oplog for CRDT
convergence — quarantine is a graph-layer concern, not an oplog concern.
Sourcepub fn apply_all(&mut self, entries: &[&Entry])
pub fn apply_all(&mut self, entries: &[&Entry])
Apply a sequence of entries (full rematerialization from op log).
Sourcepub fn rebuild(&mut self, entries: &[&Entry])
pub fn rebuild(&mut self, entries: &[&Entry])
Rebuild from scratch: clear everything and replay all entries.
Sourcepub fn get_node(&self, node_id: &str) -> Option<&Node>
pub fn get_node(&self, node_id: &str) -> Option<&Node>
Get a node by ID (returns None if not found or tombstoned).
Sourcepub fn get_edge(&self, edge_id: &str) -> Option<&Edge>
pub fn get_edge(&self, edge_id: &str) -> Option<&Edge>
Get an edge by ID (returns None if not found or tombstoned).
Sourcepub fn nodes_by_type(&self, node_type: &str) -> Vec<&Node>
pub fn nodes_by_type(&self, node_type: &str) -> Vec<&Node>
Query all live nodes of a given type.
Sourcepub fn nodes_by_subtype(&self, subtype: &str) -> Vec<&Node>
pub fn nodes_by_subtype(&self, subtype: &str) -> Vec<&Node>
Query all live nodes of a given subtype.
Sourcepub fn nodes_by_property(&self, key: &str, value: &Value) -> Vec<&Node>
pub fn nodes_by_property(&self, key: &str, value: &Value) -> Vec<&Node>
Query nodes by a property value.
Sourcepub fn outgoing_edges(&self, node_id: &str) -> Vec<&Edge>
pub fn outgoing_edges(&self, node_id: &str) -> Vec<&Edge>
Get outgoing edges for a node (only live edges with live endpoints).
Sourcepub fn incoming_edges(&self, node_id: &str) -> Vec<&Edge>
pub fn incoming_edges(&self, node_id: &str) -> Vec<&Edge>
Get incoming edges for a node (only live edges with live endpoints).
Sourcepub fn neighbors(&self, node_id: &str) -> Vec<&str>
pub fn neighbors(&self, node_id: &str) -> Vec<&str>
Neighbors of a node (connected via outgoing edges).
Sourcepub fn reverse_neighbors(&self, node_id: &str) -> Vec<&str>
pub fn reverse_neighbors(&self, node_id: &str) -> Vec<&str>
Reverse neighbors (connected via incoming edges).