nexir_mvcc/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 /// The provided per-key planning budget is invalid.
98 #[error("invalid per-key gc budget: max_versions_examined must be > 0")]
99 InvalidKeyGcBudget,
100}
101
102/// Error during codec operations.
103#[derive(Error, Debug, Clone, PartialEq, Eq)]
104pub enum CodecError {
105 /// An error occurred during encoding.
106 #[error("encode error: {0}")]
107 Encode(String),
108 /// An error occurred during decoding.
109 #[error("decode error: {0}")]
110 Decode(String),
111}
112
113/// Error during a direct or guarded batch.
114#[derive(Error, Debug, Clone, PartialEq, Eq)]
115pub enum BatchError {
116 /// The batch contained no write operations.
117 #[error("batch is empty")]
118 EmptyBatch,
119 /// The commit timestamp is less than or equal to a guard's read timestamp.
120 #[error("invalid commit timestamp: commit_ts {commit_ts} <= read_ts {read_ts}")]
121 InvalidCommitTimestamp {
122 /// The read timestamp of the guard.
123 read_ts: Timestamp,
124 /// The invalid commit timestamp.
125 commit_ts: Timestamp,
126 },
127 /// The commit timestamp is older than the latest committed version for a key.
128 #[error("commit timestamp too old: key {key:?} at {commit_ts}, latest is {latest_commit_ts}")]
129 CommitTsTooOld {
130 /// The key that caused the error.
131 key: Vec<u8>,
132 /// The requested commit timestamp.
133 commit_ts: Timestamp,
134 /// The latest committed version's timestamp.
135 latest_commit_ts: Timestamp,
136 },
137 /// A guarded batch was submitted without any read guards.
138 #[error("guarded batch requires at least one read guard")]
139 NoReadGuards,
140 /// The batch contains multiple physical writes for the same key.
141 #[error("duplicate key in batch: {key:?}")]
142 DuplicateKeyInBatch {
143 /// The duplicate key.
144 key: Vec<u8>,
145 },
146 /// A key in the batch is currently locked by an active intent.
147 #[error("key is locked by an active intent: key {key:?}, txn_id {txn_id}")]
148 KeyLocked {
149 /// The locked key.
150 key: Vec<u8>,
151 /// The transaction ID holding the lock.
152 txn_id: TxnId,
153 },
154 /// A read guard failed because a newer version exists after the `read_ts`.
155 #[error(
156 "read guard failed: newer version exists after read_ts {read_ts} for key {key:?} (actual_commit_ts: {actual_commit_ts})"
157 )]
158 GuardFailedNewerVersion {
159 /// The key that failed the guard.
160 key: Vec<u8>,
161 /// The read timestamp of the guard.
162 read_ts: Timestamp,
163 /// The timestamp of the newer version.
164 actual_commit_ts: Timestamp,
165 },
166 /// A read guard failed because the actual version did not match the expected version.
167 #[error(
168 "read guard failed: expected commit_ts {expected:?} but found {actual:?} for key {key:?}"
169 )]
170 GuardFailedVersionMismatch {
171 /// The key that failed the guard.
172 key: Vec<u8>,
173 /// The expected commit timestamp (or None if expected absent).
174 expected: Option<Timestamp>,
175 /// The actual commit timestamp found (or None if actually absent).
176 actual: Option<Timestamp>,
177 },
178 /// A read guard failed because the actual logical value did not match the expected value.
179 #[error("read guard failed: expected value mismatch for key {key:?}")]
180 GuardFailedValueMismatch {
181 /// The key that failed the guard.
182 key: Vec<u8>,
183 },
184 /// An error returned by the backend storage.
185 #[error("backend error: {0}")]
186 Backend(String),
187}
188
189/// Error during a prewrite batch.
190#[derive(Error, Debug, Clone, PartialEq, Eq)]
191pub enum BatchPrewriteError {
192 /// The batch contained no write operations.
193 #[error("batch is empty")]
194 EmptyBatch,
195 /// The batch contains multiple writes for the same key.
196 #[error("duplicate key in batch: {key:?}")]
197 DuplicateKeyInBatch {
198 /// The duplicate key.
199 key: Vec<u8>,
200 },
201 /// A key in the batch is currently locked by another active transaction.
202 #[error("key is locked by another transaction: key {key:?}, txn_id {txn_id}")]
203 KeyLocked {
204 /// The locked key.
205 key: Vec<u8>,
206 /// The transaction ID holding the lock.
207 txn_id: TxnId,
208 },
209 /// A committed version exists that is newer than the transaction's start_ts.
210 #[error("write conflict: committed version after start_ts for key {key:?}")]
211 WriteConflict {
212 /// The key that caused the conflict.
213 key: Vec<u8>,
214 },
215 /// An intent already exists for the same transaction but with different parameters.
216 #[error("intent already exists with different parameters for key {key:?}")]
217 IntentAlreadyExists {
218 /// The key with the conflicting intent.
219 key: Vec<u8>,
220 },
221 /// The batch is a partial replay, meaning some intents exist while others do not.
222 #[error("partial batch replay detected: some keys have intents, others are missing")]
223 PartialBatchReplay,
224 /// An error returned by the backend storage.
225 #[error("backend error: {0}")]
226 Backend(String),
227}
228
229/// Error during a commit batch.
230#[derive(Error, Debug, Clone, PartialEq, Eq)]
231pub enum BatchCommitError {
232 /// The batch contained no commit operations.
233 #[error("batch is empty")]
234 EmptyBatch,
235 /// The batch contains multiple commits for the same key.
236 #[error("duplicate key in batch: {key:?}")]
237 DuplicateKeyInBatch {
238 /// The duplicate key.
239 key: Vec<u8>,
240 },
241 /// The intent to be committed was not found.
242 #[error("intent not found for key {key:?}")]
243 IntentNotFound {
244 /// The key whose intent is missing.
245 key: Vec<u8>,
246 },
247 /// The transaction ID on the intent does not match the commit request.
248 #[error("txn_id mismatch for key {key:?}")]
249 TxnIdMismatch {
250 /// The key with the mismatched transaction ID.
251 key: Vec<u8>,
252 },
253 /// The start timestamp on the intent does not match the commit request.
254 #[error("start_ts mismatch for key {key:?}")]
255 StartTsMismatch {
256 /// The key with the mismatched start timestamp.
257 key: Vec<u8>,
258 },
259 /// The commit timestamp is less than or equal to the start timestamp.
260 #[error("invalid commit timestamp: commit_ts {commit_ts} <= start_ts {start_ts}")]
261 InvalidCommitTimestamp {
262 /// The start timestamp of the transaction.
263 start_ts: Timestamp,
264 /// The invalid commit timestamp.
265 commit_ts: Timestamp,
266 },
267 /// The commit timestamp is earlier than the intent's required minimum commit timestamp.
268 #[error("commit_ts {commit_ts} is before required minimum {min_commit_ts} for key {key:?}")]
269 CommitTsTooEarly {
270 /// The key failing the minimum commit timestamp check.
271 key: Vec<u8>,
272 /// The requested commit timestamp.
273 commit_ts: Timestamp,
274 /// The minimum allowed commit timestamp.
275 min_commit_ts: Timestamp,
276 },
277 /// The commit timestamp is older than the latest committed version for a key.
278 #[error("commit timestamp too old: key {key:?} at {commit_ts}, latest is {latest_commit_ts}")]
279 CommitTsTooOld {
280 /// The key that caused the error.
281 key: Vec<u8>,
282 /// The requested commit timestamp.
283 commit_ts: Timestamp,
284 /// The latest committed version's timestamp.
285 latest_commit_ts: Timestamp,
286 },
287 /// An error returned by the backend storage.
288 #[error("backend error: {0}")]
289 Backend(String),
290}
291
292/// Error during a batch abort operation.
293#[derive(Error, Debug, Clone, PartialEq, Eq)]
294pub enum BatchAbortError {
295 /// The batch contains multiple aborts for the same key.
296 #[error("duplicate key in batch: {key:?}")]
297 DuplicateKeyInBatch {
298 /// The duplicate key.
299 key: Vec<u8>,
300 },
301 /// An error returned by the backend storage.
302 #[error("backend error: {0}")]
303 Backend(String),
304}