reifydb_store_single/tier.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4//! Common storage tier traits and types.
5//!
6//! This module defines the minimal interface that all storage tiers (hot, warm, cold)
7//! must implement for single-version storage.
8
9use std::ops::Bound;
10
11use reifydb_type::{Result, util::cowvec::CowVec};
12
13/// A raw storage entry.
14///
15/// Value is None for tombstones (deletions).
16#[derive(Debug, Clone)]
17pub struct RawEntry {
18 pub key: CowVec<u8>,
19 pub value: Option<CowVec<u8>>,
20}
21
22/// A batch of range results with continuation info for pagination.
23#[derive(Debug, Clone)]
24pub struct RangeBatch {
25 /// The entries in this batch.
26 pub entries: Vec<RawEntry>,
27 /// Whether there are more entries after this batch.
28 pub has_more: bool,
29}
30
31impl RangeBatch {
32 /// Creates an empty batch with no more results.
33 pub fn empty() -> Self {
34 Self {
35 entries: Vec::new(),
36 has_more: false,
37 }
38 }
39
40 /// Returns true if this batch contains no entries.
41 pub fn is_empty(&self) -> bool {
42 self.entries.is_empty()
43 }
44}
45
46/// Cursor state for streaming range queries.
47///
48/// Tracks position within a range scan, enabling efficient continuation
49/// across multiple batches without re-scanning from the beginning.
50#[derive(Debug, Clone)]
51pub struct RangeCursor {
52 /// Last key seen in the previous batch (for Bound::Excluded continuation)
53 pub last_key: Option<CowVec<u8>>,
54 /// Whether this stream is exhausted
55 pub exhausted: bool,
56}
57
58impl RangeCursor {
59 /// Create a new cursor at the start of a range.
60 pub fn new() -> Self {
61 Self {
62 last_key: None,
63 exhausted: false,
64 }
65 }
66
67 /// Check if the stream is exhausted.
68 pub fn is_exhausted(&self) -> bool {
69 self.exhausted
70 }
71}
72
73impl Default for RangeCursor {
74 fn default() -> Self {
75 Self::new()
76 }
77}
78
79/// The tier storage trait for single-version storage.
80///
81/// This is intentionally minimal - just raw bytes in/out with no version history.
82/// Single-version storage maintains only the current value for each key.
83///
84/// Implementations must be thread-safe and cloneable.
85
86pub trait TierStorage: Send + Sync + Clone + 'static {
87 /// Get the value for a key, or None if not found.
88 fn get(&self, key: &[u8]) -> Result<Option<CowVec<u8>>>;
89
90 /// Check if a key exists in storage.
91 fn contains(&self, key: &[u8]) -> Result<bool> {
92 Ok(self.get(key)?.is_some())
93 }
94
95 /// Write entries atomically.
96 ///
97 /// All entries are written in a single transaction.
98 /// This ensures durability and atomicity for commits.
99 fn set(&self, entries: Vec<(CowVec<u8>, Option<CowVec<u8>>)>) -> Result<()>;
100
101 /// Fetch the next batch of entries in key order (descending).
102 ///
103 /// Uses the cursor to track position. On first call, cursor should be new.
104 /// On subsequent calls, pass the same cursor to continue from where left off.
105 /// Returns up to `batch_size` entries. The cursor is updated with the last
106 /// key seen, and `exhausted` is set to true when no more entries remain.
107 fn range_next(
108 &self,
109 cursor: &mut RangeCursor,
110 start: Bound<&[u8]>,
111 end: Bound<&[u8]>,
112 batch_size: usize,
113 ) -> Result<RangeBatch>;
114
115 /// Fetch the next batch of entries in reverse key order (ascending).
116 ///
117 /// Uses the cursor to track position. On first call, cursor should be new.
118 /// On subsequent calls, pass the same cursor to continue from where left off.
119 /// Returns up to `batch_size` entries. The cursor is updated with the last
120 /// key seen, and `exhausted` is set to true when no more entries remain.
121 fn range_rev_next(
122 &self,
123 cursor: &mut RangeCursor,
124 start: Bound<&[u8]>,
125 end: Bound<&[u8]>,
126 batch_size: usize,
127 ) -> Result<RangeBatch>;
128
129 /// Ensure storage is initialized.
130 ///
131 /// This may create necessary storage structures if needed.
132 fn ensure_table(&self) -> Result<()>;
133
134 /// Delete all entries in storage.
135 fn clear_table(&self) -> Result<()>;
136}
137
138/// Marker trait for storage tiers that support the tier storage interface.
139pub trait TierBackend: TierStorage {}