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