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}