Skip to main content

reifydb_store_multi/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4#![cfg_attr(not(debug_assertions), deny(clippy::disallowed_methods))]
5#![cfg_attr(debug_assertions, warn(clippy::disallowed_methods))]
6#![cfg_attr(not(debug_assertions), deny(warnings))]
7#![allow(clippy::tabs_in_doc_comments)]
8
9use reifydb_core::{
10	event::EventBus,
11	interface::version::{ComponentType, HasVersion, SystemVersion},
12};
13use reifydb_value::Result;
14
15pub mod filter;
16pub mod flush;
17pub mod tier;
18
19pub mod config;
20pub mod store;
21
22use std::{collections::HashMap, ops::Bound, sync::Arc};
23
24use config::{CommitStoreConfig, MultiStoreConfig};
25use reifydb_codec::key::encoded::{EncodedKey, EncodedKeyRange};
26use reifydb_core::{
27	common::CommitVersion,
28	delta::Delta,
29	interface::{
30		catalog::storage::StorageId,
31		store::{
32			MultiVersionCommit, MultiVersionContains, MultiVersionGet, MultiVersionGetPrevious,
33			MultiVersionRow, MultiVersionStore,
34		},
35	},
36	key::{
37		any::TaggedKey,
38		row::{StoragePartitionedRowKey, StorageRowKey},
39	},
40	metrics::collect::MetricsCollector,
41};
42use reifydb_filter::adaptive::FilterMetrics;
43use reifydb_runtime::shutdown::Shutdown;
44#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
45use reifydb_sqlite::SqliteTempPathGuard;
46use reifydb_store::metrics::PageCacheMetrics;
47use reifydb_store_commit::{
48	MultiVersionScope, VersionedGetResult,
49	store::{CommitStore, MultiCommitMetrics},
50};
51use reifydb_value::util::cowvec::CowVec;
52use store::{MultiPersistentProbeMetrics, StandardMultiStore};
53use tier::{point::MultiPointShardMetrics, range::MultiRangeShardMetrics};
54
55pub mod memory {}
56pub mod sqlite {}
57
58pub struct MultiStoreVersion;
59
60impl HasVersion for MultiStoreVersion {
61	fn version(&self) -> SystemVersion {
62		SystemVersion {
63			name: env!("CARGO_PKG_NAME")
64				.strip_prefix("reifydb-")
65				.unwrap_or(env!("CARGO_PKG_NAME"))
66				.to_string(),
67			version: env!("CARGO_PKG_VERSION").to_string(),
68			description: "Multi-version storage for OLTP operations with MVCC support".to_string(),
69			r#type: ComponentType::Module,
70		}
71	}
72}
73
74#[repr(u8)]
75#[derive(Clone)]
76pub enum MultiStore {
77	Standard(StandardMultiStore) = 0,
78}
79
80impl MultiStore {
81	pub fn standard(config: MultiStoreConfig) -> Self {
82		Self::Standard(StandardMultiStore::new(config).unwrap())
83	}
84}
85
86impl MultiStore {
87	pub fn testing_memory() -> Self {
88		MultiStore::Standard(StandardMultiStore::testing_memory())
89	}
90
91	pub fn testing_memory_with_eventbus(event_bus: EventBus) -> Self {
92		MultiStore::Standard(StandardMultiStore::testing_memory_with_eventbus(event_bus))
93	}
94
95	#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
96	pub fn testing_memory_with_persistent_sqlite() -> (Self, SqliteTempPathGuard) {
97		let (store, guard) = StandardMultiStore::testing_memory_with_persistent_sqlite();
98		(MultiStore::Standard(store), guard)
99	}
100
101	#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
102	pub fn testing_memory_with_persistent_sqlite_with_eventbus(event_bus: EventBus) -> (Self, SqliteTempPathGuard) {
103		let (store, guard) = StandardMultiStore::testing_memory_with_persistent_sqlite_with_eventbus(event_bus);
104		(MultiStore::Standard(store), guard)
105	}
106
107	pub fn flush_pending_blocking(&self) {
108		match self {
109			MultiStore::Standard(store) => store.flush_pending_blocking(),
110		}
111	}
112
113	pub fn flush_all_blocking(&self) {
114		match self {
115			MultiStore::Standard(store) => store.flush_all_blocking(),
116		}
117	}
118
119	pub fn commit(&self) -> &CommitStore {
120		match self {
121			MultiStore::Standard(store) => store.commit(),
122		}
123	}
124
125	pub fn metrics_collectors(&self) -> Vec<Arc<dyn MetricsCollector>> {
126		match self {
127			MultiStore::Standard(store) => store.metrics_collectors(),
128		}
129	}
130
131	pub fn range_shard_metrics(&self) -> Vec<MultiRangeShardMetrics> {
132		match self {
133			MultiStore::Standard(store) => store.range_shard_metrics(),
134		}
135	}
136
137	pub fn point_shard_metrics(&self) -> Vec<MultiPointShardMetrics> {
138		match self {
139			MultiStore::Standard(store) => store.point_shard_metrics(),
140		}
141	}
142
143	pub fn commit_metrics(&self) -> MultiCommitMetrics {
144		match self {
145			MultiStore::Standard(store) => store.commit_metrics(),
146		}
147	}
148
149	pub fn persistent_page_cache_metrics(&self) -> Option<PageCacheMetrics> {
150		match self {
151			MultiStore::Standard(store) => store.persistent_page_cache_metrics(),
152		}
153	}
154
155	pub fn persistent_probe_metrics(&self) -> Option<MultiPersistentProbeMetrics> {
156		match self {
157			MultiStore::Standard(store) => store.persistent_probe_metrics(),
158		}
159	}
160
161	pub fn persistent_filter_metrics(&self) -> Option<FilterMetrics> {
162		match self {
163			MultiStore::Standard(store) => store.persistent_filter_metrics(),
164		}
165	}
166
167	pub fn persistent(&self) -> Option<&tier::persistent::MultiPersistentTier> {
168		match self {
169			MultiStore::Standard(store) => store.persistent(),
170		}
171	}
172
173	pub fn clear_eviction_watermark(&self) {
174		match self {
175			MultiStore::Standard(store) => store.clear_eviction_watermark(),
176		}
177	}
178}
179
180impl Shutdown for MultiStore {
181	fn shutdown(&self) {
182		match self {
183			MultiStore::Standard(store) => store.shutdown(),
184		}
185	}
186}
187
188impl MultiVersionGet for MultiStore {
189	#[inline]
190	fn get(&self, key: &TaggedKey, version: CommitVersion) -> Result<Option<MultiVersionRow<TaggedKey>>> {
191		match self {
192			MultiStore::Standard(store) => MultiVersionGet::get(store, key, version),
193		}
194	}
195}
196
197impl MultiVersionContains for MultiStore {
198	#[inline]
199	fn contains(&self, key: &TaggedKey, version: CommitVersion) -> Result<bool> {
200		match self {
201			MultiStore::Standard(store) => MultiVersionContains::contains(store, key, version),
202		}
203	}
204}
205
206impl MultiVersionCommit for MultiStore {
207	#[inline]
208	fn commit(&self, deltas: CowVec<Delta>, version: CommitVersion) -> Result<()> {
209		match self {
210			MultiStore::Standard(store) => MultiVersionCommit::commit(store, deltas, version),
211		}
212	}
213}
214
215impl MultiVersionGetPrevious for MultiStore {
216	#[inline]
217	fn get_previous_version(
218		&self,
219		key: &TaggedKey,
220		before_version: CommitVersion,
221	) -> Result<Option<MultiVersionRow<TaggedKey>>> {
222		match self {
223			MultiStore::Standard(store) => store.get_previous_version(key, before_version),
224		}
225	}
226}
227
228pub type MultiVersionRangeIterator<'a> = Box<dyn Iterator<Item = Result<MultiVersionRow<TaggedKey>>> + Send + 'a>;
229pub type MultiVersionRowRangeIterator<'a> =
230	Box<dyn Iterator<Item = Result<MultiVersionRow<StorageRowKey>>> + Send + 'a>;
231pub type MultiVersionPartitionedRowRangeIterator<'a> =
232	Box<dyn Iterator<Item = Result<MultiVersionRow<StoragePartitionedRowKey>>> + Send + 'a>;
233
234impl MultiStore {
235	pub fn range(
236		&self,
237		range: EncodedKeyRange,
238		scope: MultiVersionScope,
239		batch_size: usize,
240	) -> MultiVersionRangeIterator<'_> {
241		match self {
242			MultiStore::Standard(store) => Box::new(store.range(range, scope, batch_size)),
243		}
244	}
245
246	pub fn range_row(
247		&self,
248		storage: StorageId,
249		start: Bound<StorageRowKey>,
250		end: Bound<StorageRowKey>,
251		scope: MultiVersionScope,
252		batch_size: usize,
253	) -> MultiVersionRowRangeIterator<'_> {
254		match self {
255			MultiStore::Standard(store) => {
256				Box::new(store.range_row(storage, start, end, scope, batch_size))
257			}
258		}
259	}
260
261	pub fn range_partitioned_row(
262		&self,
263		storage: StorageId,
264		start: Bound<StoragePartitionedRowKey>,
265		end: Bound<StoragePartitionedRowKey>,
266		scope: MultiVersionScope,
267		batch_size: usize,
268	) -> MultiVersionPartitionedRowRangeIterator<'_> {
269		match self {
270			MultiStore::Standard(store) => {
271				Box::new(store.range_partitioned_row(storage, start, end, scope, batch_size))
272			}
273		}
274	}
275
276	pub fn range_persistence(
277		&self,
278		range: EncodedKeyRange,
279		scope: MultiVersionScope,
280		batch_size: usize,
281	) -> MultiVersionRangeIterator<'_> {
282		match self {
283			MultiStore::Standard(store) => Box::new(store.range_persistence(range, scope, batch_size)),
284		}
285	}
286
287	pub fn range_rev(
288		&self,
289		range: EncodedKeyRange,
290		scope: MultiVersionScope,
291		batch_size: usize,
292	) -> MultiVersionRangeIterator<'_> {
293		match self {
294			MultiStore::Standard(store) => Box::new(store.range_rev(range, scope, batch_size)),
295		}
296	}
297
298	pub fn range_rev_persistence(
299		&self,
300		range: EncodedKeyRange,
301		scope: MultiVersionScope,
302		batch_size: usize,
303	) -> MultiVersionRangeIterator<'_> {
304		match self {
305			MultiStore::Standard(store) => Box::new(store.range_rev_persistence(range, scope, batch_size)),
306		}
307	}
308
309	pub fn get_many(
310		&self,
311		keys: &[EncodedKey],
312		version: CommitVersion,
313	) -> Result<HashMap<EncodedKey, MultiVersionRow>> {
314		match self {
315			MultiStore::Standard(store) => store.get_many(keys, version),
316		}
317	}
318
319	pub fn get_many_versioned(
320		&self,
321		keys: &[EncodedKey],
322		version: CommitVersion,
323	) -> Result<HashMap<EncodedKey, VersionedGetResult>> {
324		match self {
325			MultiStore::Standard(store) => store.get_many_versioned(keys, version),
326		}
327	}
328}
329
330impl MultiVersionStore for MultiStore {}