Skip to main content

GraphBackend

Trait GraphBackend 

Source
pub trait GraphBackend {
Show 30 methods // Required methods fn insert_node(&self, node: NodeSpec) -> Result<i64, SqliteGraphError>; fn insert_edge(&self, edge: EdgeSpec) -> Result<i64, SqliteGraphError>; fn update_node( &self, node_id: i64, node: NodeSpec, ) -> Result<i64, SqliteGraphError>; fn delete_entity(&self, id: i64) -> Result<(), SqliteGraphError>; fn entity_ids(&self) -> Result<Vec<i64>, SqliteGraphError>; fn get_node( &self, snapshot_id: SnapshotId, id: i64, ) -> Result<GraphEntity, SqliteGraphError>; fn neighbors( &self, snapshot_id: SnapshotId, node: i64, query: NeighborQuery, ) -> Result<Vec<i64>, SqliteGraphError>; fn bfs( &self, snapshot_id: SnapshotId, start: i64, depth: u32, ) -> Result<Vec<i64>, SqliteGraphError>; fn shortest_path( &self, snapshot_id: SnapshotId, start: i64, end: i64, ) -> Result<Option<Vec<i64>>, SqliteGraphError>; fn node_degree( &self, snapshot_id: SnapshotId, node: i64, ) -> Result<(usize, usize), SqliteGraphError>; fn k_hop( &self, snapshot_id: SnapshotId, start: i64, depth: u32, direction: BackendDirection, ) -> Result<Vec<i64>, SqliteGraphError>; fn k_hop_filtered( &self, snapshot_id: SnapshotId, start: i64, depth: u32, direction: BackendDirection, allowed_edge_types: &[&str], ) -> Result<Vec<i64>, SqliteGraphError>; fn chain_query( &self, snapshot_id: SnapshotId, start: i64, chain: &[ChainStep], ) -> Result<Vec<i64>, SqliteGraphError>; fn pattern_search( &self, snapshot_id: SnapshotId, start: i64, pattern: &PatternQuery, ) -> Result<Vec<PatternMatch>, SqliteGraphError>; fn checkpoint(&self) -> Result<(), SqliteGraphError>; fn flush(&self) -> Result<(), SqliteGraphError>; fn backup( &self, backup_dir: &Path, ) -> Result<BackupResult, SqliteGraphError>; fn snapshot_export( &self, export_dir: &Path, ) -> Result<SnapshotMetadata, SqliteGraphError>; fn snapshot_import( &self, import_dir: &Path, ) -> Result<ImportMetadata, SqliteGraphError>; fn kv_get( &self, snapshot_id: SnapshotId, key: &[u8], ) -> Result<Option<KvValue>, SqliteGraphError>; fn kv_set( &self, key: Vec<u8>, value: KvValue, ttl_seconds: Option<u64>, ) -> Result<(), SqliteGraphError>; fn kv_delete(&self, key: &[u8]) -> Result<(), SqliteGraphError>; fn subscribe( &self, filter: SubscriptionFilter, ) -> Result<(u64, Receiver<PubSubEvent>), SqliteGraphError>; fn unsubscribe(&self, subscriber_id: u64) -> Result<bool, SqliteGraphError>; fn kv_prefix_scan( &self, snapshot_id: SnapshotId, prefix: &[u8], ) -> Result<Vec<(Vec<u8>, KvValue)>, SqliteGraphError>; fn query_nodes_by_kind( &self, snapshot_id: SnapshotId, kind: &str, ) -> Result<Vec<i64>, SqliteGraphError>; fn query_nodes_by_name_pattern( &self, snapshot_id: SnapshotId, pattern: &str, ) -> Result<Vec<i64>, SqliteGraphError>; // Provided methods fn all_entity_ids(&self) -> Result<Vec<i64>, SqliteGraphError> { ... } fn fetch_outgoing(&self, node: i64) -> Result<Vec<i64>, SqliteGraphError> { ... } fn fetch_incoming(&self, node: i64) -> Result<Vec<i64>, SqliteGraphError> { ... }
}
Expand description

Each trait method delegates to backend-specific primitives while ensuring deterministic behavior and a single integration surface for consumers.

§Snapshot Isolation

All read operations require a snapshot_id: SnapshotId parameter to enforce ACID compliance. Reads only observe data committed at or before the snapshot.

Required Methods§

Source

fn insert_node(&self, node: NodeSpec) -> Result<i64, SqliteGraphError>

Source

fn insert_edge(&self, edge: EdgeSpec) -> Result<i64, SqliteGraphError>

Source

fn update_node( &self, node_id: i64, node: NodeSpec, ) -> Result<i64, SqliteGraphError>

Update an existing node in place without allocating a new node ID

This modifies the data associated with an existing node while preserving its node_id.

§Arguments
  • node_id - The ID of the node to update (must exist)
  • node - New node specification (kind, name, file_path, data)
§Returns

The same node_id that was passed in, if update succeeded

§Errors

Returns SqliteGraphError if:

  • The node_id doesn’t exist
  • The update operation fails
  • The backend doesn’t support in-place updates
§Behavior by Backend
  • Native: Uses WAL to update node data in place, preserving node_id
  • SQLite: Uses UPDATE SQL query on entities table
§Example
// Create a node
let node_id = backend.insert_node(NodeSpec {
    kind: "File".to_string(),
    name: "main.rs".to_string(),
    file_path: Some("main.rs".to_string()),
    data: serde_json::json!({"hash": "abc123"}),
})?;

// Update it - this does NOT allocate a new node_id
let updated_id = backend.update_node(node_id, NodeSpec {
    kind: "File".to_string(),
    name: "main.rs".to_string(),
    file_path: Some("main.rs".to_string()),
    data: serde_json::json!({"hash": "def456", "modified": true}),
})?;

assert_eq!(updated_id, node_id); // Same ID!
Source

fn delete_entity(&self, id: i64) -> Result<(), SqliteGraphError>

Delete an entity (node) from the graph by ID

This removes the entity and all associated edges from the graph. For SQLite backend: deletes from entities table and cascades to edges For Native backend: marks node as deleted and updates adjacency indexes

Source

fn entity_ids(&self) -> Result<Vec<i64>, SqliteGraphError>

Get all entity IDs from the graph

Returns a vector of all node IDs currently stored in the graph. For SQLite backend: queries all IDs from entities table For Native backend: iterates over node store

Source

fn get_node( &self, snapshot_id: SnapshotId, id: i64, ) -> Result<GraphEntity, SqliteGraphError>

Source

fn neighbors( &self, snapshot_id: SnapshotId, node: i64, query: NeighborQuery, ) -> Result<Vec<i64>, SqliteGraphError>

Source

fn bfs( &self, snapshot_id: SnapshotId, start: i64, depth: u32, ) -> Result<Vec<i64>, SqliteGraphError>

Source

fn shortest_path( &self, snapshot_id: SnapshotId, start: i64, end: i64, ) -> Result<Option<Vec<i64>>, SqliteGraphError>

Source

fn node_degree( &self, snapshot_id: SnapshotId, node: i64, ) -> Result<(usize, usize), SqliteGraphError>

Source

fn k_hop( &self, snapshot_id: SnapshotId, start: i64, depth: u32, direction: BackendDirection, ) -> Result<Vec<i64>, SqliteGraphError>

Source

fn k_hop_filtered( &self, snapshot_id: SnapshotId, start: i64, depth: u32, direction: BackendDirection, allowed_edge_types: &[&str], ) -> Result<Vec<i64>, SqliteGraphError>

Source

fn chain_query( &self, snapshot_id: SnapshotId, start: i64, chain: &[ChainStep], ) -> Result<Vec<i64>, SqliteGraphError>

Source

fn checkpoint(&self) -> Result<(), SqliteGraphError>

Trigger WAL checkpoint for backends that support write-ahead logging

For Native backend with WAL: flushes WAL to graph file For SQLite backend: executes PRAGMA wal_checkpoint(TRUNCATE) For backends without WAL: returns Ok(()) as no-op

Source

fn flush(&self) -> Result<(), SqliteGraphError>

Force immediate flush of WAL buffer to disk

Ensures all buffered WAL records (including KV writes) are persisted immediately, making them visible to other processes.

For Native backend with WAL: flushes WAL buffer to disk For SQLite backend: returns Ok(()) as no-op (SQLite handles sync) For backends without WAL: returns Ok(()) as no-op

Source

fn backup(&self, backup_dir: &Path) -> Result<BackupResult, SqliteGraphError>

Create a backup of the database

Creates a consistent snapshot of the database including all data pages.

§Arguments
  • backup_dir - Destination directory for backup files
§Returns

Backup result with paths, checksum, and metadata

Source

fn snapshot_export( &self, export_dir: &Path, ) -> Result<SnapshotMetadata, SqliteGraphError>

Export database snapshot to the specified directory

Creates a consistent snapshot of the current database state. For Native backend: uses snapshot format For SQLite backend: uses JSON dump format

§Arguments
  • export_dir - Directory path where snapshot will be written
§Returns

Snapshot metadata including file paths and size information

Source

fn snapshot_import( &self, import_dir: &Path, ) -> Result<ImportMetadata, SqliteGraphError>

Import database snapshot from the specified directory

Restores database state from a previously created snapshot. For Native backend: loads snapshot format For SQLite backend: loads JSON dump format

§Arguments
  • import_dir - Directory path containing snapshot files
§Returns

Import metadata including number of records imported

Source

fn kv_get( &self, snapshot_id: SnapshotId, key: &[u8], ) -> Result<Option<KvValue>, SqliteGraphError>

Get a value from the KV store at the given snapshot

§Arguments
  • snapshot_id - Only return data committed at or before this snapshot
  • key - Key to retrieve (arbitrary bytes)
§Returns

The value if found and visible at snapshot, or None if not found

Source

fn kv_set( &self, key: Vec<u8>, value: KvValue, ttl_seconds: Option<u64>, ) -> Result<(), SqliteGraphError>

Set a value in the KV store

This operation participates in the current transaction and will be committed atomically with other graph operations.

§Arguments
  • key - Key to set (arbitrary bytes)
  • value - Value to store
  • ttl_seconds - Optional TTL in seconds (None = no expiration)
Source

fn kv_delete(&self, key: &[u8]) -> Result<(), SqliteGraphError>

Delete a value from the KV store

This operation participates in the current transaction and will be committed atomically with other graph operations.

§Arguments
  • key - Key to delete
Source

fn subscribe( &self, filter: SubscriptionFilter, ) -> Result<(u64, Receiver<PubSubEvent>), SqliteGraphError>

Subscribe to graph change events

Returns a subscriber ID and a receiver channel for events. The receiver will receive events that match the given filter.

§Events

Events are emitted ONLY on transaction commit:

  • NodeChanged - node created or modified
  • EdgeChanged - edge created or modified
  • KvChanged - KV entry created, modified, or deleted
  • SnapshotCommitted - transaction committed
§Best-Effort Delivery
  • No persistence of events
  • If receiver is dropped, events are silently dropped
  • If channel is full, events are silently dropped
  • No delivery guarantees
§Example
let (sub_id, rx) = graph.subscribe(SubscriptionFilter::all());
// In another thread/task:
for event in rx {
    match event {
        PubSubEvent::NodeChanged { node_id, snapshot_id } => {
            // Read node state at snapshot_id
        }
        _ => {}
    }
}
}
Source

fn unsubscribe(&self, subscriber_id: u64) -> Result<bool, SqliteGraphError>

Unsubscribe from events

Cancels the subscription and stops receiving events. Returns true if subscription existed and was removed.

§Arguments
  • subscriber_id - The subscriber ID returned by subscribe()
Source

fn kv_prefix_scan( &self, snapshot_id: SnapshotId, prefix: &[u8], ) -> Result<Vec<(Vec<u8>, KvValue)>, SqliteGraphError>

Scan all KV entries with a given prefix

Returns all keys that start with the given prefix, along with their values. Results are in lexicographic order by key.

§Arguments
  • snapshot_id - Only return data committed at or before this snapshot
  • prefix - Prefix to match (empty prefix returns all keys)
§Returns

Vector of (key, value) pairs for all matching keys

Source

fn query_nodes_by_kind( &self, snapshot_id: SnapshotId, kind: &str, ) -> Result<Vec<i64>, SqliteGraphError>

Query all nodes with a given kind

Returns all node IDs where the node’s kind equals the given string. Results are sorted by node ID for deterministic output.

§Arguments
  • snapshot_id - Only return data committed at or before this snapshot
  • kind - Kind string to match (case-sensitive)
§Returns

Vector of node IDs with matching kind

Source

fn query_nodes_by_name_pattern( &self, snapshot_id: SnapshotId, pattern: &str, ) -> Result<Vec<i64>, SqliteGraphError>

Query nodes by name pattern using glob matching

Returns all node IDs where the node’s label matches the glob pattern. Pattern syntax:

  • * matches any sequence of characters
  • ? matches exactly one character
§Arguments
  • snapshot_id - Only return data committed at or before this snapshot
  • pattern - Glob pattern to match against node labels
§Returns

Vector of node IDs with matching labels

Provided Methods§

Source

fn all_entity_ids(&self) -> Result<Vec<i64>, SqliteGraphError>

Alias for entity_ids() for backward compatibility with algorithms

Default implementation delegates to entity_ids().

Source

fn fetch_outgoing(&self, node: i64) -> Result<Vec<i64>, SqliteGraphError>

Get outgoing neighbors for a node (convenience method)

Default implementation uses neighbors with Outgoing direction.

Source

fn fetch_incoming(&self, node: i64) -> Result<Vec<i64>, SqliteGraphError>

Get incoming neighbors for a node (convenience method)

Default implementation uses neighbors with Incoming direction.

Implementations on Foreign Types§

Source§

impl<B> GraphBackend for &B
where B: GraphBackend + ?Sized,

Reference implementation for GraphBackend trait that works with references.

Source§

fn insert_node(&self, node: NodeSpec) -> Result<i64, SqliteGraphError>

Source§

fn get_node( &self, snapshot_id: SnapshotId, id: i64, ) -> Result<GraphEntity, SqliteGraphError>

Source§

fn insert_edge(&self, edge: EdgeSpec) -> Result<i64, SqliteGraphError>

Source§

fn update_node( &self, node_id: i64, node: NodeSpec, ) -> Result<i64, SqliteGraphError>

Source§

fn delete_entity(&self, id: i64) -> Result<(), SqliteGraphError>

Source§

fn entity_ids(&self) -> Result<Vec<i64>, SqliteGraphError>

Source§

fn neighbors( &self, snapshot_id: SnapshotId, node: i64, query: NeighborQuery, ) -> Result<Vec<i64>, SqliteGraphError>

Source§

fn bfs( &self, snapshot_id: SnapshotId, start: i64, depth: u32, ) -> Result<Vec<i64>, SqliteGraphError>

Source§

fn shortest_path( &self, snapshot_id: SnapshotId, start: i64, end: i64, ) -> Result<Option<Vec<i64>>, SqliteGraphError>

Source§

fn node_degree( &self, snapshot_id: SnapshotId, node: i64, ) -> Result<(usize, usize), SqliteGraphError>

Source§

fn k_hop( &self, snapshot_id: SnapshotId, start: i64, depth: u32, direction: BackendDirection, ) -> Result<Vec<i64>, SqliteGraphError>

Source§

fn k_hop_filtered( &self, snapshot_id: SnapshotId, start: i64, depth: u32, direction: BackendDirection, allowed_edge_types: &[&str], ) -> Result<Vec<i64>, SqliteGraphError>

Source§

fn chain_query( &self, snapshot_id: SnapshotId, start: i64, chain: &[ChainStep], ) -> Result<Vec<i64>, SqliteGraphError>

Source§

fn checkpoint(&self) -> Result<(), SqliteGraphError>

Source§

fn flush(&self) -> Result<(), SqliteGraphError>

Source§

fn backup(&self, backup_dir: &Path) -> Result<BackupResult, SqliteGraphError>

Source§

fn snapshot_export( &self, export_dir: &Path, ) -> Result<SnapshotMetadata, SqliteGraphError>

Source§

fn snapshot_import( &self, import_dir: &Path, ) -> Result<ImportMetadata, SqliteGraphError>

Source§

fn kv_get( &self, snapshot_id: SnapshotId, key: &[u8], ) -> Result<Option<KvValue>, SqliteGraphError>

Source§

fn kv_set( &self, key: Vec<u8>, value: KvValue, ttl_seconds: Option<u64>, ) -> Result<(), SqliteGraphError>

Source§

fn kv_delete(&self, key: &[u8]) -> Result<(), SqliteGraphError>

Source§

fn subscribe( &self, filter: SubscriptionFilter, ) -> Result<(u64, Receiver<PubSubEvent>), SqliteGraphError>

Source§

fn unsubscribe(&self, subscriber_id: u64) -> Result<bool, SqliteGraphError>

Source§

fn kv_prefix_scan( &self, snapshot_id: SnapshotId, prefix: &[u8], ) -> Result<Vec<(Vec<u8>, KvValue)>, SqliteGraphError>

Source§

fn query_nodes_by_kind( &self, snapshot_id: SnapshotId, kind: &str, ) -> Result<Vec<i64>, SqliteGraphError>

Source§

fn query_nodes_by_name_pattern( &self, snapshot_id: SnapshotId, pattern: &str, ) -> Result<Vec<i64>, SqliteGraphError>

Implementors§