Skip to main content

nodedb_lite/storage/
vector_segment_ext.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! `VectorSegmentExt` — pagedb segment operations for HNSW vector data.
4//!
5//! The `StorageEngine` trait handles sparse, sorted, key-value state.  For
6//! HNSW vector data (large, sequentially accessed, zero-copy win) pagedb
7//! segments are more appropriate.  This trait exposes exactly the three
8//! operations the HNSW persistence layer needs without leaking pagedb types
9//! into caller code.
10//!
11//! Only compiled on non-WASM targets because `pagedb::MmapView` (used by
12//! `PagedbBacking`) requires mmap.  WASM stays on the blob path.
13
14use crate::engine::vector::pagedb_backing::PagedbBacking;
15use crate::error::LiteError;
16
17/// Extension trait: write, open, and delete HNSW vector segments backed by
18/// pagedb encrypted segment files.
19///
20/// Implementors are responsible for translating between the generic NDVS byte
21/// stream and the pagedb segment page layout.
22///
23/// This trait is object-safe so `StorageEngine` implementations can return
24/// `Option<&dyn VectorSegmentExt>` via `as_vector_segment_ext()`.
25#[async_trait::async_trait]
26pub trait VectorSegmentExt: Send + Sync {
27    /// Write a vector segment for `collection_name`.
28    ///
29    /// Serialises the NDVS v2 format in memory, chunks it into 4 KiB pagedb
30    /// pages, creates a new encrypted segment, and links it under
31    /// `vec/hnsw/{collection_name}`.  If a segment already exists under that
32    /// name it is atomically replaced (old segment is tombstoned and will be
33    /// reaped by the next `Db::gc_now` call).
34    ///
35    /// `vectors[i]` corresponds to node `i`; `surrogate_ids` must either be
36    /// empty or have the same length as `vectors`.
37    async fn write_vector_segment(
38        &self,
39        collection_name: &str,
40        dim: usize,
41        vectors: &[Vec<f32>],
42        surrogate_ids: &[u64],
43    ) -> Result<(), LiteError>;
44
45    /// Open a previously written vector segment for `collection_name`.
46    ///
47    /// Returns `None` if no segment exists under `vec/hnsw/{collection_name}`.
48    async fn open_vector_segment(
49        &self,
50        collection_name: &str,
51    ) -> Result<Option<PagedbBacking>, LiteError>;
52
53    /// Delete the vector segment for `collection_name`.
54    ///
55    /// No-op if no segment exists.  The segment file is tombstoned and will be
56    /// removed by the next `Db::gc_now` cycle.
57    async fn delete_vector_segment(&self, collection_name: &str) -> Result<(), LiteError>;
58}