reifydb-store-multi 0.9.1

Multi-version storage for OLTP operations with MVCC support
Documentation
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2026 ReifyDB

#![cfg_attr(not(debug_assertions), deny(clippy::disallowed_methods))]
#![cfg_attr(debug_assertions, warn(clippy::disallowed_methods))]
#![cfg_attr(not(debug_assertions), deny(warnings))]
#![allow(clippy::tabs_in_doc_comments)]

use reifydb_core::{
	event::EventBus,
	interface::version::{ComponentType, HasVersion, SystemVersion},
};
use reifydb_value::Result;

pub mod filter;
pub mod flush;
pub mod tier;

pub mod config;
pub mod store;

use std::{collections::HashMap, ops::Bound, sync::Arc};

use config::{CommitStoreConfig, MultiStoreConfig};
use reifydb_codec::key::encoded::{EncodedKey, EncodedKeyRange};
use reifydb_core::{
	common::CommitVersion,
	delta::Delta,
	interface::{
		catalog::storage::StorageId,
		store::{
			MultiVersionCommit, MultiVersionContains, MultiVersionGet, MultiVersionGetPrevious,
			MultiVersionRow, MultiVersionStore,
		},
	},
	key::{
		any::TaggedKey,
		row::{StoragePartitionedRowKey, StorageRowKey},
	},
	metrics::collect::MetricsCollector,
};
use reifydb_filter::adaptive::FilterMetrics;
use reifydb_runtime::shutdown::Shutdown;
#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
use reifydb_sqlite::SqliteTempPathGuard;
use reifydb_store::metrics::PageCacheMetrics;
use reifydb_store_commit::{
	MultiVersionScope, VersionedGetResult,
	store::{CommitStore, MultiCommitMetrics},
};
use reifydb_value::util::cowvec::CowVec;
use store::{MultiPersistentProbeMetrics, StandardMultiStore};
use tier::{point::MultiPointShardMetrics, range::MultiRangeShardMetrics};

pub mod memory {}
pub mod sqlite {}

pub struct MultiStoreVersion;

impl HasVersion for MultiStoreVersion {
	fn version(&self) -> SystemVersion {
		SystemVersion {
			name: env!("CARGO_PKG_NAME")
				.strip_prefix("reifydb-")
				.unwrap_or(env!("CARGO_PKG_NAME"))
				.to_string(),
			version: env!("CARGO_PKG_VERSION").to_string(),
			description: "Multi-version storage for OLTP operations with MVCC support".to_string(),
			r#type: ComponentType::Module,
		}
	}
}

#[repr(u8)]
#[derive(Clone)]
pub enum MultiStore {
	Standard(StandardMultiStore) = 0,
}

impl MultiStore {
	pub fn standard(config: MultiStoreConfig) -> Self {
		Self::Standard(StandardMultiStore::new(config).unwrap())
	}
}

impl MultiStore {
	pub fn testing_memory() -> Self {
		MultiStore::Standard(StandardMultiStore::testing_memory())
	}

	pub fn testing_memory_with_eventbus(event_bus: EventBus) -> Self {
		MultiStore::Standard(StandardMultiStore::testing_memory_with_eventbus(event_bus))
	}

	#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
	pub fn testing_memory_with_persistent_sqlite() -> (Self, SqliteTempPathGuard) {
		let (store, guard) = StandardMultiStore::testing_memory_with_persistent_sqlite();
		(MultiStore::Standard(store), guard)
	}

	#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
	pub fn testing_memory_with_persistent_sqlite_with_eventbus(event_bus: EventBus) -> (Self, SqliteTempPathGuard) {
		let (store, guard) = StandardMultiStore::testing_memory_with_persistent_sqlite_with_eventbus(event_bus);
		(MultiStore::Standard(store), guard)
	}

	pub fn flush_pending_blocking(&self) {
		match self {
			MultiStore::Standard(store) => store.flush_pending_blocking(),
		}
	}

	pub fn flush_all_blocking(&self) {
		match self {
			MultiStore::Standard(store) => store.flush_all_blocking(),
		}
	}

	pub fn commit(&self) -> &CommitStore {
		match self {
			MultiStore::Standard(store) => store.commit(),
		}
	}

	pub fn metrics_collectors(&self) -> Vec<Arc<dyn MetricsCollector>> {
		match self {
			MultiStore::Standard(store) => store.metrics_collectors(),
		}
	}

	pub fn range_shard_metrics(&self) -> Vec<MultiRangeShardMetrics> {
		match self {
			MultiStore::Standard(store) => store.range_shard_metrics(),
		}
	}

	pub fn point_shard_metrics(&self) -> Vec<MultiPointShardMetrics> {
		match self {
			MultiStore::Standard(store) => store.point_shard_metrics(),
		}
	}

	pub fn commit_metrics(&self) -> MultiCommitMetrics {
		match self {
			MultiStore::Standard(store) => store.commit_metrics(),
		}
	}

	pub fn persistent_page_cache_metrics(&self) -> Option<PageCacheMetrics> {
		match self {
			MultiStore::Standard(store) => store.persistent_page_cache_metrics(),
		}
	}

	pub fn persistent_probe_metrics(&self) -> Option<MultiPersistentProbeMetrics> {
		match self {
			MultiStore::Standard(store) => store.persistent_probe_metrics(),
		}
	}

	pub fn persistent_filter_metrics(&self) -> Option<FilterMetrics> {
		match self {
			MultiStore::Standard(store) => store.persistent_filter_metrics(),
		}
	}

	pub fn persistent(&self) -> Option<&tier::persistent::MultiPersistentTier> {
		match self {
			MultiStore::Standard(store) => store.persistent(),
		}
	}

	pub fn clear_eviction_watermark(&self) {
		match self {
			MultiStore::Standard(store) => store.clear_eviction_watermark(),
		}
	}
}

impl Shutdown for MultiStore {
	fn shutdown(&self) {
		match self {
			MultiStore::Standard(store) => store.shutdown(),
		}
	}
}

impl MultiVersionGet for MultiStore {
	#[inline]
	fn get(&self, key: &TaggedKey, version: CommitVersion) -> Result<Option<MultiVersionRow<TaggedKey>>> {
		match self {
			MultiStore::Standard(store) => MultiVersionGet::get(store, key, version),
		}
	}
}

impl MultiVersionContains for MultiStore {
	#[inline]
	fn contains(&self, key: &TaggedKey, version: CommitVersion) -> Result<bool> {
		match self {
			MultiStore::Standard(store) => MultiVersionContains::contains(store, key, version),
		}
	}
}

impl MultiVersionCommit for MultiStore {
	#[inline]
	fn commit(&self, deltas: CowVec<Delta>, version: CommitVersion) -> Result<()> {
		match self {
			MultiStore::Standard(store) => MultiVersionCommit::commit(store, deltas, version),
		}
	}
}

impl MultiVersionGetPrevious for MultiStore {
	#[inline]
	fn get_previous_version(
		&self,
		key: &TaggedKey,
		before_version: CommitVersion,
	) -> Result<Option<MultiVersionRow<TaggedKey>>> {
		match self {
			MultiStore::Standard(store) => store.get_previous_version(key, before_version),
		}
	}
}

pub type MultiVersionRangeIterator<'a> = Box<dyn Iterator<Item = Result<MultiVersionRow<TaggedKey>>> + Send + 'a>;
pub type MultiVersionRowRangeIterator<'a> =
	Box<dyn Iterator<Item = Result<MultiVersionRow<StorageRowKey>>> + Send + 'a>;
pub type MultiVersionPartitionedRowRangeIterator<'a> =
	Box<dyn Iterator<Item = Result<MultiVersionRow<StoragePartitionedRowKey>>> + Send + 'a>;

impl MultiStore {
	pub fn range(
		&self,
		range: EncodedKeyRange,
		scope: MultiVersionScope,
		batch_size: usize,
	) -> MultiVersionRangeIterator<'_> {
		match self {
			MultiStore::Standard(store) => Box::new(store.range(range, scope, batch_size)),
		}
	}

	pub fn range_row(
		&self,
		storage: StorageId,
		start: Bound<StorageRowKey>,
		end: Bound<StorageRowKey>,
		scope: MultiVersionScope,
		batch_size: usize,
	) -> MultiVersionRowRangeIterator<'_> {
		match self {
			MultiStore::Standard(store) => {
				Box::new(store.range_row(storage, start, end, scope, batch_size))
			}
		}
	}

	pub fn range_partitioned_row(
		&self,
		storage: StorageId,
		start: Bound<StoragePartitionedRowKey>,
		end: Bound<StoragePartitionedRowKey>,
		scope: MultiVersionScope,
		batch_size: usize,
	) -> MultiVersionPartitionedRowRangeIterator<'_> {
		match self {
			MultiStore::Standard(store) => {
				Box::new(store.range_partitioned_row(storage, start, end, scope, batch_size))
			}
		}
	}

	pub fn range_persistence(
		&self,
		range: EncodedKeyRange,
		scope: MultiVersionScope,
		batch_size: usize,
	) -> MultiVersionRangeIterator<'_> {
		match self {
			MultiStore::Standard(store) => Box::new(store.range_persistence(range, scope, batch_size)),
		}
	}

	pub fn range_rev(
		&self,
		range: EncodedKeyRange,
		scope: MultiVersionScope,
		batch_size: usize,
	) -> MultiVersionRangeIterator<'_> {
		match self {
			MultiStore::Standard(store) => Box::new(store.range_rev(range, scope, batch_size)),
		}
	}

	pub fn range_rev_persistence(
		&self,
		range: EncodedKeyRange,
		scope: MultiVersionScope,
		batch_size: usize,
	) -> MultiVersionRangeIterator<'_> {
		match self {
			MultiStore::Standard(store) => Box::new(store.range_rev_persistence(range, scope, batch_size)),
		}
	}

	pub fn get_many(
		&self,
		keys: &[EncodedKey],
		version: CommitVersion,
	) -> Result<HashMap<EncodedKey, MultiVersionRow>> {
		match self {
			MultiStore::Standard(store) => store.get_many(keys, version),
		}
	}

	pub fn get_many_versioned(
		&self,
		keys: &[EncodedKey],
		version: CommitVersion,
	) -> Result<HashMap<EncodedKey, VersionedGetResult>> {
		match self {
			MultiStore::Standard(store) => store.get_many_versioned(keys, version),
		}
	}
}

impl MultiVersionStore for MultiStore {}