qml_rs/storage/
error.rs

1use crate::error::QmlError;
2use thiserror::Error;
3
4/// Storage-specific errors that can occur during job persistence operations
5#[derive(Error, Debug)]
6pub enum StorageError {
7    /// Connection-related errors (network, authentication, etc.)
8    #[error("Storage connection error: {message}")]
9    Connection {
10        message: String,
11        #[source]
12        source: Option<Box<dyn std::error::Error + Send + Sync>>,
13    },
14
15    /// Serialization/deserialization errors when converting jobs to/from storage format
16    #[error("Serialization error: {message}")]
17    Serialization {
18        message: String,
19        #[source]
20        source: Option<Box<dyn std::error::Error + Send + Sync>>,
21    },
22
23    /// Job not found in storage
24    #[error("Job not found: {job_id}")]
25    JobNotFound { job_id: String },
26
27    /// Storage operation timed out
28    #[error("Storage operation timed out after {timeout_ms}ms")]
29    Timeout { timeout_ms: u64 },
30
31    /// Storage is unavailable or down
32    #[error("Storage is unavailable: {reason}")]
33    Unavailable { reason: String },
34
35    /// Configuration errors
36    #[error("Storage configuration error: {message}")]
37    Configuration { message: String },
38
39    /// General storage operation errors
40    #[error("Storage operation failed: {operation} - {message}")]
41    OperationFailed {
42        operation: String,
43        message: String,
44        #[source]
45        source: Option<Box<dyn std::error::Error + Send + Sync>>,
46    },
47
48    /// Storage capacity exceeded
49    #[error("Storage capacity exceeded: {message}")]
50    CapacityExceeded { message: String },
51
52    /// Concurrent modification detected
53    #[error("Concurrent modification detected for job: {job_id}")]
54    ConcurrentModification { job_id: String },
55
56    /// Database migration errors
57    #[error("Migration error: {message}")]
58    MigrationError { message: String },
59
60    /// Invalid job data format
61    #[error("Invalid job data: {message}")]
62    InvalidJobData { message: String },
63
64    /// Connection-specific error (shorthand)
65    #[error("Connection error: {message}")]
66    ConnectionError { message: String },
67
68    /// Serialization-specific error (shorthand)
69    #[error("Serialization error: {message}")]
70    SerializationError { message: String },
71
72    /// Deserialization-specific error (shorthand)
73    #[error("Deserialization error: {message}")]
74    DeserializationError { message: String },
75
76    /// Operation-specific error (shorthand)
77    #[error("Operation error: {message}")]
78    OperationError { message: String },
79}
80
81impl StorageError {
82    /// Create a connection error with a message
83    pub fn connection<S: Into<String>>(message: S) -> Self {
84        Self::Connection {
85            message: message.into(),
86            source: None,
87        }
88    }
89
90    /// Create a connection error with a message and source error
91    pub fn connection_with_source<S: Into<String>>(
92        message: S,
93        source: Box<dyn std::error::Error + Send + Sync>,
94    ) -> Self {
95        Self::Connection {
96            message: message.into(),
97            source: Some(source),
98        }
99    }
100
101    /// Create a serialization error with a message
102    pub fn serialization<S: Into<String>>(message: S) -> Self {
103        Self::Serialization {
104            message: message.into(),
105            source: None,
106        }
107    }
108
109    /// Create a serialization error with a message and source error
110    pub fn serialization_with_source<S: Into<String>>(
111        message: S,
112        source: Box<dyn std::error::Error + Send + Sync>,
113    ) -> Self {
114        Self::Serialization {
115            message: message.into(),
116            source: Some(source),
117        }
118    }
119
120    /// Create a job not found error
121    pub fn job_not_found<S: Into<String>>(job_id: S) -> Self {
122        Self::JobNotFound {
123            job_id: job_id.into(),
124        }
125    }
126
127    /// Create a timeout error
128    pub fn timeout(timeout_ms: u64) -> Self {
129        Self::Timeout { timeout_ms }
130    }
131
132    /// Create an unavailable error
133    pub fn unavailable<S: Into<String>>(reason: S) -> Self {
134        Self::Unavailable {
135            reason: reason.into(),
136        }
137    }
138
139    /// Create a configuration error
140    pub fn configuration<S: Into<String>>(message: S) -> Self {
141        Self::Configuration {
142            message: message.into(),
143        }
144    }
145
146    /// Create an operation failed error
147    pub fn operation_failed<S: Into<String>, T: Into<String>>(operation: S, message: T) -> Self {
148        Self::OperationFailed {
149            operation: operation.into(),
150            message: message.into(),
151            source: None,
152        }
153    }
154
155    /// Create an operation failed error with source
156    pub fn operation_failed_with_source<S: Into<String>, T: Into<String>>(
157        operation: S,
158        message: T,
159        source: Box<dyn std::error::Error + Send + Sync>,
160    ) -> Self {
161        Self::OperationFailed {
162            operation: operation.into(),
163            message: message.into(),
164            source: Some(source),
165        }
166    }
167
168    /// Create a capacity exceeded error
169    pub fn capacity_exceeded<S: Into<String>>(message: S) -> Self {
170        Self::CapacityExceeded {
171            message: message.into(),
172        }
173    }
174
175    /// Create a concurrent modification error
176    pub fn concurrent_modification<S: Into<String>>(job_id: S) -> Self {
177        Self::ConcurrentModification {
178            job_id: job_id.into(),
179        }
180    }
181}
182
183// Convert StorageError to QmlError for unified error handling
184impl From<StorageError> for QmlError {
185    fn from(err: StorageError) -> Self {
186        match err {
187            StorageError::JobNotFound { job_id } => QmlError::JobNotFound { job_id },
188            StorageError::Serialization { message, .. } => QmlError::SerializationError { message },
189            _ => QmlError::StorageError {
190                message: err.to_string(),
191            },
192        }
193    }
194}