Skip to main content

reifydb_store_multi/tier/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4pub mod commit;
5pub mod persistent;
6pub mod read;
7
8use std::{collections::HashMap, ops::Bound};
9
10use reifydb_core::{common::CommitVersion, encoded::key::EncodedKey, interface::store::EntryKind};
11use reifydb_value::{Result, util::cowvec::CowVec};
12
13use crate::MultiVersionScope;
14
15pub type TierBatch = HashMap<EntryKind, Vec<(EncodedKey, Option<CowVec<u8>>)>>;
16
17#[derive(Debug, Clone)]
18pub enum VersionedGetResult {
19	Value {
20		value: CowVec<u8>,
21		version: CommitVersion,
22	},
23
24	Tombstone,
25
26	NotFound,
27}
28
29impl VersionedGetResult {
30	pub fn value(self) -> Option<CowVec<u8>> {
31		match self {
32			VersionedGetResult::Value {
33				value,
34				..
35			} => Some(value),
36			VersionedGetResult::Tombstone | VersionedGetResult::NotFound => None,
37		}
38	}
39}
40
41#[derive(Debug, Clone)]
42pub struct RawEntry {
43	pub key: EncodedKey,
44	pub version: CommitVersion,
45	pub value: Option<CowVec<u8>>,
46}
47
48#[derive(Debug, Clone)]
49pub struct RangeBatch {
50	pub entries: Vec<RawEntry>,
51
52	pub has_more: bool,
53}
54
55impl RangeBatch {
56	pub fn empty() -> Self {
57		Self {
58			entries: Vec::new(),
59			has_more: false,
60		}
61	}
62
63	pub fn is_empty(&self) -> bool {
64		self.entries.is_empty()
65	}
66}
67
68#[derive(Debug, Clone)]
69pub struct RangeCursor {
70	pub last_key: Option<EncodedKey>,
71
72	pub exhausted: bool,
73}
74
75#[derive(Debug, Clone, Default)]
76pub struct HistoricalCursor {
77	pub last_key: Option<EncodedKey>,
78	pub last_version: Option<CommitVersion>,
79	pub exhausted: bool,
80}
81
82impl HistoricalCursor {
83	pub fn new() -> Self {
84		Self::default()
85	}
86
87	pub fn is_exhausted(&self) -> bool {
88		self.exhausted
89	}
90}
91
92impl RangeCursor {
93	pub fn new() -> Self {
94		Self {
95			last_key: None,
96			exhausted: false,
97		}
98	}
99
100	pub fn is_exhausted(&self) -> bool {
101		self.exhausted
102	}
103}
104
105impl Default for RangeCursor {
106	fn default() -> Self {
107		Self::new()
108	}
109}
110
111pub trait TierStorage: Send + Sync + Clone + 'static {
112	fn get(&self, table: EntryKind, key: &[u8], version: CommitVersion) -> Result<VersionedGetResult>;
113
114	fn get_many(
115		&self,
116		table: EntryKind,
117		keys: &[&[u8]],
118		version: CommitVersion,
119	) -> Result<Vec<VersionedGetResult>> {
120		let mut out = Vec::with_capacity(keys.len());
121		for &key in keys {
122			out.push(self.get(table, key, version)?);
123		}
124		Ok(out)
125	}
126
127	fn contains(&self, table: EntryKind, key: &[u8], version: CommitVersion) -> Result<bool> {
128		Ok(matches!(self.get(table, key, version)?, VersionedGetResult::Value { .. }))
129	}
130
131	fn set(&self, version: CommitVersion, batches: TierBatch) -> Result<()>;
132
133	fn range_next(
134		&self,
135		table: EntryKind,
136		cursor: &mut RangeCursor,
137		start: Bound<&[u8]>,
138		end: Bound<&[u8]>,
139		scope: MultiVersionScope,
140		batch_size: usize,
141	) -> Result<RangeBatch>;
142
143	fn range_rev_next(
144		&self,
145		table: EntryKind,
146		cursor: &mut RangeCursor,
147		start: Bound<&[u8]>,
148		end: Bound<&[u8]>,
149		scope: MultiVersionScope,
150		batch_size: usize,
151	) -> Result<RangeBatch>;
152
153	fn ensure_table(&self, table: EntryKind) -> Result<()>;
154
155	fn clear_table(&self, table: EntryKind) -> Result<()>;
156
157	fn drop(&self, batches: HashMap<EntryKind, Vec<(EncodedKey, CommitVersion)>>) -> Result<()>;
158
159	fn get_all_versions(&self, table: EntryKind, key: &[u8]) -> Result<Vec<(CommitVersion, Option<CowVec<u8>>)>>;
160
161	fn scan_historical_below(
162		&self,
163		table: EntryKind,
164		cutoff: CommitVersion,
165		cursor: &mut HistoricalCursor,
166		batch_size: usize,
167	) -> Result<Vec<(EncodedKey, CommitVersion)>>;
168}
169
170pub trait TierBackend: TierStorage {}