log/error.rs
1//! Error types for OpenData Log operations.
2//!
3//! This module defines [`Error`], the primary error type for all log
4//! operations, along with a convenient [`Result`] type alias.
5
6use common::{SequenceError, StorageError};
7
8/// Error type for OpenData Log operations.
9///
10/// This enum captures all possible error conditions that can occur when
11/// interacting with the log, including storage failures, encoding issues,
12/// and invalid input.
13///
14/// # Error Categories
15///
16/// - [`Storage`](Error::Storage): Errors from the underlying SlateDB storage layer,
17/// such as I/O failures or corruption.
18/// - [`Encoding`](Error::Encoding): Errors during serialization or deserialization
19/// of log entries.
20/// - [`InvalidInput`](Error::InvalidInput): Errors caused by invalid parameters or
21/// arguments provided by the caller.
22/// - [`Internal`](Error::Internal): Unexpected internal errors that indicate bugs
23/// or invariant violations.
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum Error {
26 /// Storage-related errors from the underlying SlateDB layer.
27 ///
28 /// These errors typically indicate I/O failures, corruption, or
29 /// issues with the object store backend.
30 Storage(String),
31
32 /// Encoding or decoding errors.
33 ///
34 /// These errors occur when serializing records for storage or
35 /// deserializing entries during reads.
36 Encoding(String),
37
38 /// Invalid input or parameter errors.
39 ///
40 /// These errors indicate that the caller provided invalid arguments,
41 /// such as empty keys or malformed sequence ranges.
42 InvalidInput(String),
43
44 /// Internal errors indicating bugs or invariant violations.
45 ///
46 /// These errors should not occur during normal operation and
47 /// typically indicate a bug in the implementation.
48 Internal(String),
49}
50
51impl std::error::Error for Error {}
52
53impl std::fmt::Display for Error {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 match self {
56 Error::Storage(msg) => write!(f, "Storage error: {}", msg),
57 Error::Encoding(msg) => write!(f, "Encoding error: {}", msg),
58 Error::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
59 Error::Internal(msg) => write!(f, "Internal error: {}", msg),
60 }
61 }
62}
63
64impl From<StorageError> for Error {
65 fn from(err: StorageError) -> Self {
66 match err {
67 StorageError::Storage(msg) => Error::Storage(msg),
68 StorageError::Internal(msg) => Error::Internal(msg),
69 }
70 }
71}
72
73impl From<SequenceError> for Error {
74 fn from(err: SequenceError) -> Self {
75 match err {
76 SequenceError::Storage(storage_err) => Error::from(storage_err),
77 SequenceError::Deserialize(de_err) => Error::Encoding(de_err.message),
78 }
79 }
80}
81
82impl From<&str> for Error {
83 fn from(msg: &str) -> Self {
84 Error::InvalidInput(msg.to_string())
85 }
86}
87
88/// Result type alias for OpenData Log operations.
89///
90/// This is a convenience alias for `std::result::Result<T, Error>`.
91pub type Result<T> = std::result::Result<T, Error>;
92
93use crate::model::Record;
94
95/// Error type for append operations that preserves the batch for retry.
96///
97/// Unlike [`Error`], this type carries the original `Vec<Record>` inside
98/// retryable variants (`QueueFull`, `Timeout`) so callers can retry without
99/// cloning the batch up front.
100#[derive(Debug)]
101pub enum AppendError {
102 /// The write queue is full (non-blocking send failed). Contains the batch.
103 QueueFull(Vec<Record>),
104 /// Timed out waiting for queue space. Contains the batch.
105 Timeout(Vec<Record>),
106 /// The writer has shut down.
107 Shutdown,
108 /// A storage-level error occurred while processing the write.
109 Storage(String),
110}
111
112impl AppendError {
113 /// Returns the batch of records if this is a retryable error, or `None`
114 /// for terminal errors.
115 pub fn into_inner(self) -> Option<Vec<Record>> {
116 match self {
117 AppendError::QueueFull(records) => Some(records),
118 AppendError::Timeout(records) => Some(records),
119 AppendError::Shutdown => None,
120 AppendError::Storage(_) => None,
121 }
122 }
123}
124
125impl std::fmt::Display for AppendError {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 match self {
128 AppendError::QueueFull(_) => write!(f, "write queue full"),
129 AppendError::Timeout(_) => write!(f, "write queue timeout"),
130 AppendError::Shutdown => write!(f, "writer shut down"),
131 AppendError::Storage(msg) => write!(f, "storage error: {}", msg),
132 }
133 }
134}
135
136impl std::error::Error for AppendError {}
137
138impl From<AppendError> for Error {
139 fn from(err: AppendError) -> Self {
140 match err {
141 AppendError::QueueFull(_) => Error::Internal("write queue full".into()),
142 AppendError::Timeout(_) => Error::Internal("write queue timeout".into()),
143 AppendError::Shutdown => Error::Internal("writer shut down".into()),
144 AppendError::Storage(msg) => Error::Internal(msg),
145 }
146 }
147}
148
149/// Result type alias for append operations.
150///
151/// This is a convenience alias for `std::result::Result<T, AppendError>`.
152pub type AppendResult<T> = std::result::Result<T, AppendError>;