Skip to main content

reifydb_store_multi/tier/
mod.rs

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