Skip to main content

velesdb_core/collection/vector_collection/
lifecycle.rs

1//! Constructor and persistence methods for `VectorCollection`.
2
3use std::path::PathBuf;
4
5use crate::collection::types::Collection;
6use crate::distance::DistanceMetric;
7use crate::error::Result;
8use crate::quantization::StorageMode;
9
10use super::VectorCollection;
11
12impl VectorCollection {
13    /// Creates a new `VectorCollection` at the given path.
14    ///
15    /// # Errors
16    ///
17    /// Returns an error if the directory cannot be created or storage fails.
18    pub fn create(
19        path: PathBuf,
20        _name: &str,
21        dimension: usize,
22        metric: DistanceMetric,
23        storage_mode: StorageMode,
24    ) -> Result<Self> {
25        Ok(Self {
26            inner: Collection::create_with_options(path, dimension, metric, storage_mode)?,
27        })
28    }
29
30    /// Creates a new `VectorCollection` with custom HNSW parameters.
31    ///
32    /// When `m` or `ef_construction` are `Some`, those values override the
33    /// auto-tuned defaults; every other HNSW field stays at the
34    /// dimension-based auto-tuned default.
35    ///
36    /// Shortcut for [`VectorCollection::create_with_params`] that only
37    /// overrides `max_connections` and `ef_construction`. It passes
38    /// `pq_rescore_oversampling = None` — "no explicit override", which is
39    /// **not** what [`VectorCollection::create`] persists (that one takes the
40    /// engine default `Some(4)`), so the two are not interchangeable even
41    /// when both arguments are `None`. Use
42    /// [`VectorCollection::create_with_hnsw_params`] for a params override
43    /// that keeps the `create` PQ default.
44    ///
45    /// # Errors
46    ///
47    /// Returns an error if the directory cannot be created or storage fails.
48    pub fn create_with_hnsw(
49        path: PathBuf,
50        _name: &str,
51        dimension: usize,
52        metric: DistanceMetric,
53        storage_mode: StorageMode,
54        m: Option<usize>,
55        ef_construction: Option<usize>,
56    ) -> Result<Self> {
57        let mut params = crate::index::hnsw::HnswParams::auto(dimension);
58        if let Some(m) = m {
59            params.max_connections = m;
60        }
61        if let Some(ef) = ef_construction {
62            params.ef_construction = ef;
63        }
64        params.storage_mode = storage_mode;
65        Self::create_with_params(path, dimension, metric, storage_mode, params, None)
66    }
67
68    /// Creates a new `VectorCollection` with fully specified
69    /// [`HnswParams`](crate::index::hnsw::HnswParams), keeping the
70    /// `pq_rescore_oversampling` engine default of `Some(4)`.
71    ///
72    /// This is the constructor a params object resolved from the `[hnsw]`
73    /// config section goes through (see `Database::resolve_hnsw_params`). It
74    /// differs from [`VectorCollection::create`] in the HNSW parameters and
75    /// in nothing else — notably not in `pq_rescore_oversampling`, which
76    /// [`VectorCollection::create_with_hnsw`] does change. Configuring
77    /// `[hnsw]` therefore alters the index topology and no other persisted
78    /// field.
79    ///
80    /// # Errors
81    ///
82    /// Returns an error if the directory cannot be created or storage fails.
83    pub fn create_with_hnsw_params(
84        path: PathBuf,
85        dimension: usize,
86        metric: DistanceMetric,
87        storage_mode: StorageMode,
88        hnsw_params: crate::index::hnsw::HnswParams,
89    ) -> Result<Self> {
90        Self::create_with_params(path, dimension, metric, storage_mode, hnsw_params, Some(4))
91    }
92
93    /// Creates a new `VectorCollection` with a fully specified
94    /// [`HnswParams`](crate::index::hnsw::HnswParams) and an explicit
95    /// `pq_rescore_oversampling` override.
96    ///
97    /// This is the most expressive constructor exposed by
98    /// `VectorCollection`: callers pass the full params object directly,
99    /// including `alpha` (VAMANA neighbour diversification),
100    /// `max_elements` (initial HNSW capacity), and any future field added
101    /// to `HnswParams`, without going through the `(m, ef_construction)`
102    /// shortcut. Passing `pq_rescore_oversampling = None` keeps the
103    /// persisted config in "no explicit override" mode so later migrations
104    /// can recompute the factor from dataset shape.
105    ///
106    /// # Errors
107    ///
108    /// Returns an error if the directory cannot be created or storage fails.
109    pub fn create_with_params(
110        path: PathBuf,
111        dimension: usize,
112        metric: DistanceMetric,
113        storage_mode: StorageMode,
114        mut hnsw_params: crate::index::hnsw::HnswParams,
115        pq_rescore_oversampling: Option<u32>,
116    ) -> Result<Self> {
117        // Make sure the storage mode baked into the params matches the
118        // per-collection storage mode argument. If a caller passed
119        // mismatching values we deliberately let the function argument
120        // win — it is the more direct, less ambiguous source.
121        hnsw_params.storage_mode = storage_mode;
122        Ok(Self {
123            inner: Collection::create_with_full_config(
124                path,
125                dimension,
126                metric,
127                storage_mode,
128                hnsw_params,
129                pq_rescore_oversampling,
130            )?,
131        })
132    }
133
134    /// Opens an existing `VectorCollection` from disk.
135    ///
136    /// # Errors
137    ///
138    /// Returns an error if the config file cannot be read or storage cannot be opened.
139    pub fn open(path: PathBuf) -> Result<Self> {
140        Ok(Self {
141            inner: Collection::open(path)?,
142        })
143    }
144
145    /// Creates a new `VectorCollection` with an async index builder configuration.
146    ///
147    /// # Errors
148    ///
149    /// Returns an error if the directory cannot be created or the config cannot be saved.
150    pub fn create_with_async_builder(
151        path: PathBuf,
152        dimension: usize,
153        metric: DistanceMetric,
154        async_builder_config: crate::collection::streaming::AsyncIndexBuilderConfig,
155    ) -> Result<Self> {
156        Ok(Self {
157            inner: Collection::create_with_async_builder(
158                path,
159                dimension,
160                metric,
161                async_builder_config,
162            )?,
163        })
164    }
165
166    /// Flushes all engines to disk and saves the config.
167    ///
168    /// Issue #423: This fast-path flush skips `vectors.idx` serialization.
169    /// The WAL provides crash recovery for the vector index.
170    ///
171    /// # Errors
172    ///
173    /// Returns an error if any flush operation fails.
174    pub fn flush(&self) -> Result<()> {
175        self.inner.flush()
176    }
177
178    /// Full durability flush including `vectors.idx` serialization.
179    ///
180    /// Issue #423: Use on graceful shutdown to avoid a full WAL replay
181    /// on the next startup.
182    ///
183    /// # Errors
184    ///
185    /// Returns an error if any flush operation fails.
186    pub fn flush_full(&self) -> Result<()> {
187        self.inner.flush_full()
188    }
189}