Skip to main content

nodedb_lite/storage/
graph_segment_ext.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! `GraphSegmentExt` — pagedb segment operations for CSR adjacency data.
4//!
5//! The `StorageEngine` trait handles sparse, sorted, key-value state.  For CSR
6//! adjacency blobs (one per graph collection, large, sequentially read on
7//! cold-open restore) pagedb segments are the appropriate backing.  A single
8//! segment per collection reduces B+ tree pressure from O(edge_count) entries
9//! to O(1) per collection.
10//!
11//! `GraphHistory` rows (bitemporal edge/node history) remain on the B+ tree
12//! (`Namespace::GraphHistory`) — they are genuinely sparse and sorted by
13//! (entity_id, valid_time).
14//!
15//! Only compiled on non-WASM targets.  WASM stays on the KV blob path.
16
17use crate::error::LiteError;
18
19/// Extension trait: write, open, and delete CSR adjacency segments backed
20/// by pagedb encrypted segment files.
21///
22/// One segment per collection (e.g. `"social_graph"`).  The segment contains
23/// the serialized CSR checkpoint bytes exactly as produced by
24/// `CsrIndex::checkpoint_to_bytes()` — no additional framing beyond the
25/// 8-byte length-prefix envelope used to survive pagedb's page-boundary
26/// zero-padding.
27///
28/// This trait is object-safe so `StorageEngine` implementations can return
29/// `Option<&dyn GraphSegmentExt>` via `as_graph_segment_ext()`.
30#[async_trait::async_trait]
31pub trait GraphSegmentExt: Send + Sync {
32    /// Write the CSR checkpoint blob for `collection`.
33    ///
34    /// Chunks the length-prefixed payload into 4 KiB pagedb pages, creates a
35    /// new encrypted segment, and links it under `graph/csr/{collection}`.
36    /// If a segment already exists under that name it is atomically replaced
37    /// (old segment is tombstoned and reaped by the next `Db::gc_now` call).
38    async fn write_graph_segment(&self, collection: &str, bytes: &[u8]) -> Result<(), LiteError>;
39
40    /// Open a previously written CSR segment for `collection`.
41    ///
42    /// Returns the raw CSR checkpoint bytes in a `Box<[u8]>`, identical to
43    /// the bytes passed to `write_graph_segment`.
44    ///
45    /// Returns `None` if no segment exists under `graph/csr/{collection}`.
46    async fn open_graph_segment(&self, collection: &str) -> Result<Option<Box<[u8]>>, LiteError>;
47
48    /// Delete the CSR segment for `collection`.
49    ///
50    /// No-op if no segment exists.  The segment file is tombstoned and reaped
51    /// by the next `Db::gc_now` cycle.
52    async fn delete_graph_segment(&self, collection: &str) -> Result<(), LiteError>;
53}