nexir_mvcc_core/error.rs
1use thiserror::Error;
2
3use crate::types::{Timestamp, TxnId};
4
5/// Error during a read operation.
6#[derive(Error, Debug, Clone, PartialEq, Eq)]
7pub enum ReadError {
8 /// An error returned by the backend storage.
9 #[error("backend error: {0}")]
10 Backend(String),
11}
12
13/// Error during a single-key prewrite operation.
14#[derive(Error, Debug, Clone, PartialEq, Eq)]
15pub enum PrewriteError {
16 /// The key is locked by another active transaction.
17 #[error("key is locked by another transaction: txn_id={txn_id}")]
18 KeyLocked {
19 /// The transaction ID currently holding the lock.
20 txn_id: TxnId,
21 },
22 /// A committed version exists that is newer than the transaction's start_ts.
23 #[error("write conflict: committed version after start_ts")]
24 WriteConflict,
25 /// An error returned by the backend storage.
26 #[error("backend error: {0}")]
27 Backend(String),
28 /// An intent already exists for the same transaction but with different parameters.
29 #[error("intent already exists with different parameters")]
30 IntentAlreadyExists,
31}
32
33/// Error during a single-key commit operation.
34#[derive(Error, Debug, Clone, PartialEq, Eq)]
35pub enum CommitError {
36 /// The intent to be committed was not found.
37 #[error("intent not found")]
38 IntentNotFound,
39 /// The transaction ID on the intent does not match the commit request.
40 #[error("txn_id mismatch")]
41 TxnIdMismatch,
42 /// The start timestamp on the intent does not match the commit request.
43 #[error("start_ts mismatch")]
44 StartTsMismatch,
45 /// The commit timestamp is less than or equal to the start timestamp.
46 #[error("invalid commit timestamp: commit_ts {commit_ts} <= start_ts {start_ts}")]
47 InvalidCommitTimestamp {
48 /// The start timestamp of the transaction.
49 start_ts: Timestamp,
50 /// The invalid commit timestamp.
51 commit_ts: Timestamp,
52 },
53 /// A committed version already exists exactly at this commit timestamp.
54 #[error("duplicate commit timestamp: {commit_ts}")]
55 DuplicateCommitTimestamp {
56 /// The duplicate commit timestamp.
57 commit_ts: Timestamp,
58 },
59 /// The commit timestamp is older than the latest committed version for a key.
60 #[error("commit timestamp too old: commit_ts {commit_ts}, latest is {latest_commit_ts}")]
61 CommitTsTooOld {
62 /// The requested commit timestamp.
63 commit_ts: Timestamp,
64 /// The latest committed version's timestamp.
65 latest_commit_ts: Timestamp,
66 },
67 /// The commit timestamp is earlier than the intent's required minimum commit timestamp.
68 #[error("commit_ts {commit_ts} is before required minimum {min_commit_ts}")]
69 CommitTsTooEarly {
70 /// The requested commit timestamp.
71 commit_ts: Timestamp,
72 /// The minimum allowed commit timestamp.
73 min_commit_ts: Timestamp,
74 },
75 /// An error returned by the backend storage.
76 #[error("backend error: {0}")]
77 Backend(String),
78}
79
80/// Error during a single-key abort operation.
81#[derive(Error, Debug, Clone, PartialEq, Eq)]
82pub enum AbortError {
83 /// An error returned by the backend storage.
84 #[error("backend error: {0}")]
85 Backend(String),
86}
87
88/// Error during garbage collection.
89#[derive(Error, Debug, Clone, PartialEq, Eq)]
90pub enum GcError {
91 /// An error returned by the backend storage.
92 #[error("backend error: {0}")]
93 Backend(String),
94 /// The provided GC budget is invalid (e.g., max_keys or max_versions is 0).
95 #[error("invalid gc budget: max_keys and max_versions must be > 0")]
96 InvalidGcBudget,
97}
98
99/// Error during codec operations.
100#[derive(Error, Debug, Clone, PartialEq, Eq)]
101pub enum CodecError {
102 /// An error occurred during encoding.
103 #[error("encode error: {0}")]
104 Encode(String),
105 /// An error occurred during decoding.
106 #[error("decode error: {0}")]
107 Decode(String),
108}
109
110/// Error during a direct or guarded batch.
111#[derive(Error, Debug, Clone, PartialEq, Eq)]
112pub enum BatchError {
113 /// The batch contained no write operations.
114 #[error("batch is empty")]
115 EmptyBatch,
116 /// The commit timestamp is less than or equal to a guard's read timestamp.
117 #[error("invalid commit timestamp: commit_ts {commit_ts} <= read_ts {read_ts}")]
118 InvalidCommitTimestamp {
119 /// The read timestamp of the guard.
120 read_ts: Timestamp,
121 /// The invalid commit timestamp.
122 commit_ts: Timestamp,
123 },
124 /// The commit timestamp is older than the latest committed version for a key.
125 #[error("commit timestamp too old: key {key:?} at {commit_ts}, latest is {latest_commit_ts}")]
126 CommitTsTooOld {
127 /// The key that caused the error.
128 key: Vec<u8>,
129 /// The requested commit timestamp.
130 commit_ts: Timestamp,
131 /// The latest committed version's timestamp.
132 latest_commit_ts: Timestamp,
133 },
134 /// A guarded batch was submitted without any read guards.
135 #[error("guarded batch requires at least one read guard")]
136 NoReadGuards,
137 /// The batch contains multiple physical writes for the same key.
138 #[error("duplicate key in batch: {key:?}")]
139 DuplicateKeyInBatch {
140 /// The duplicate key.
141 key: Vec<u8>,
142 },
143 /// A key in the batch is currently locked by an active intent.
144 #[error("key is locked by an active intent: key {key:?}, txn_id {txn_id}")]
145 KeyLocked {
146 /// The locked key.
147 key: Vec<u8>,
148 /// The transaction ID holding the lock.
149 txn_id: TxnId,
150 },
151 /// A read guard failed because a newer version exists after the `read_ts`.
152 #[error("read guard failed: newer version exists after read_ts {read_ts} for key {key:?} (actual_commit_ts: {actual_commit_ts})")]
153 GuardFailedNewerVersion {
154 /// The key that failed the guard.
155 key: Vec<u8>,
156 /// The read timestamp of the guard.
157 read_ts: Timestamp,
158 /// The timestamp of the newer version.
159 actual_commit_ts: Timestamp,
160 },
161 /// A read guard failed because the actual version did not match the expected version.
162 #[error(
163 "read guard failed: expected commit_ts {expected:?} but found {actual:?} for key {key:?}"
164 )]
165 GuardFailedVersionMismatch {
166 /// The key that failed the guard.
167 key: Vec<u8>,
168 /// The expected commit timestamp (or None if expected absent).
169 expected: Option<Timestamp>,
170 /// The actual commit timestamp found (or None if actually absent).
171 actual: Option<Timestamp>,
172 },
173 /// A read guard failed because the actual logical value did not match the expected value.
174 #[error("read guard failed: expected value mismatch for key {key:?}")]
175 GuardFailedValueMismatch {
176 /// The key that failed the guard.
177 key: Vec<u8>,
178 },
179 /// An error returned by the backend storage.
180 #[error("backend error: {0}")]
181 Backend(String),
182}
183
184/// Error during a prewrite batch.
185#[derive(Error, Debug, Clone, PartialEq, Eq)]
186pub enum BatchPrewriteError {
187 /// The batch contained no write operations.
188 #[error("batch is empty")]
189 EmptyBatch,
190 /// The batch contains multiple writes for the same key.
191 #[error("duplicate key in batch: {key:?}")]
192 DuplicateKeyInBatch {
193 /// The duplicate key.
194 key: Vec<u8>,
195 },
196 /// A key in the batch is currently locked by another active transaction.
197 #[error("key is locked by another transaction: key {key:?}, txn_id {txn_id}")]
198 KeyLocked {
199 /// The locked key.
200 key: Vec<u8>,
201 /// The transaction ID holding the lock.
202 txn_id: TxnId,
203 },
204 /// A committed version exists that is newer than the transaction's start_ts.
205 #[error("write conflict: committed version after start_ts for key {key:?}")]
206 WriteConflict {
207 /// The key that caused the conflict.
208 key: Vec<u8>,
209 },
210 /// An intent already exists for the same transaction but with different parameters.
211 #[error("intent already exists with different parameters for key {key:?}")]
212 IntentAlreadyExists {
213 /// The key with the conflicting intent.
214 key: Vec<u8>,
215 },
216 /// The batch is a partial replay, meaning some intents exist while others do not.
217 #[error("partial batch replay detected: some keys have intents, others are missing")]
218 PartialBatchReplay,
219 /// An error returned by the backend storage.
220 #[error("backend error: {0}")]
221 Backend(String),
222}
223
224/// Error during a commit batch.
225#[derive(Error, Debug, Clone, PartialEq, Eq)]
226pub enum BatchCommitError {
227 /// The batch contained no commit operations.
228 #[error("batch is empty")]
229 EmptyBatch,
230 /// The batch contains multiple commits for the same key.
231 #[error("duplicate key in batch: {key:?}")]
232 DuplicateKeyInBatch {
233 /// The duplicate key.
234 key: Vec<u8>,
235 },
236 /// The intent to be committed was not found.
237 #[error("intent not found for key {key:?}")]
238 IntentNotFound {
239 /// The key whose intent is missing.
240 key: Vec<u8>,
241 },
242 /// The transaction ID on the intent does not match the commit request.
243 #[error("txn_id mismatch for key {key:?}")]
244 TxnIdMismatch {
245 /// The key with the mismatched transaction ID.
246 key: Vec<u8>,
247 },
248 /// The start timestamp on the intent does not match the commit request.
249 #[error("start_ts mismatch for key {key:?}")]
250 StartTsMismatch {
251 /// The key with the mismatched start timestamp.
252 key: Vec<u8>,
253 },
254 /// The commit timestamp is less than or equal to the start timestamp.
255 #[error("invalid commit timestamp: commit_ts {commit_ts} <= start_ts {start_ts}")]
256 InvalidCommitTimestamp {
257 /// The start timestamp of the transaction.
258 start_ts: Timestamp,
259 /// The invalid commit timestamp.
260 commit_ts: Timestamp,
261 },
262 /// The commit timestamp is earlier than the intent's required minimum commit timestamp.
263 #[error("commit_ts {commit_ts} is before required minimum {min_commit_ts} for key {key:?}")]
264 CommitTsTooEarly {
265 /// The key failing the minimum commit timestamp check.
266 key: Vec<u8>,
267 /// The requested commit timestamp.
268 commit_ts: Timestamp,
269 /// The minimum allowed commit timestamp.
270 min_commit_ts: Timestamp,
271 },
272 /// The commit timestamp is older than the latest committed version for a key.
273 #[error("commit timestamp too old: key {key:?} at {commit_ts}, latest is {latest_commit_ts}")]
274 CommitTsTooOld {
275 /// The key that caused the error.
276 key: Vec<u8>,
277 /// The requested commit timestamp.
278 commit_ts: Timestamp,
279 /// The latest committed version's timestamp.
280 latest_commit_ts: Timestamp,
281 },
282 /// An error returned by the backend storage.
283 #[error("backend error: {0}")]
284 Backend(String),
285}
286
287/// Error during a batch abort operation.
288#[derive(Error, Debug, Clone, PartialEq, Eq)]
289pub enum BatchAbortError {
290 /// The batch contains multiple aborts for the same key.
291 #[error("duplicate key in batch: {key:?}")]
292 DuplicateKeyInBatch {
293 /// The duplicate key.
294 key: Vec<u8>,
295 },
296 /// An error returned by the backend storage.
297 #[error("backend error: {0}")]
298 Backend(String),
299}