use thiserror::Error;
pub type StorageResult<T> = Result<T, StorageError>;
#[derive(Debug, Error)]
pub enum StorageError {
#[error("Backend not available: {backend}")]
BackendNotAvailable { backend: String },
#[error("Connection error: {source}")]
ConnectionError {
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("Query error: {message}")]
QueryError { message: String },
#[error("Serialization error: {source}")]
SerializationError {
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("Deserialization error: {source}")]
DeserializationError {
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("Transaction error: {message}")]
TransactionError { message: String },
#[error("Constraint violation: {message}")]
ConstraintViolation { message: String },
#[error("Not found: {entity} with key {key}")]
NotFound { entity: String, key: String },
#[error("Already exists: {entity} with key {key}")]
AlreadyExists { entity: String, key: String },
#[error("Invalid configuration: {message}")]
InvalidConfiguration { message: String },
#[error("Operation timed out after {duration_ms}ms")]
Timeout { duration_ms: u64 },
#[error("Invalid state: {message}")]
InvalidState { message: String },
#[error("Lock error: {message}")]
LockError { message: String },
#[error("Migration error: {message}")]
MigrationError { message: String },
#[error("Unsupported operation: {operation} not supported by {backend}")]
UnsupportedOperation { operation: String, backend: String },
#[error("Internal error: {message}")]
InternalError { message: String },
#[error("Capacity exceeded: {message}")]
CapacityError { message: String },
#[error("I/O error: {source}")]
IoError {
#[from]
source: std::io::Error,
},
}
impl StorageError {
pub fn is_retryable(&self) -> bool {
matches!(
self,
StorageError::ConnectionError { .. }
| StorageError::Timeout { .. }
| StorageError::LockError { .. }
)
}
pub fn is_transient(&self) -> bool {
matches!(
self,
StorageError::ConnectionError { .. }
| StorageError::Timeout { .. }
| StorageError::LockError { .. }
| StorageError::BackendNotAvailable { .. }
)
}
pub fn category(&self) -> ErrorCategory {
match self {
StorageError::BackendNotAvailable { .. } => ErrorCategory::Availability,
StorageError::ConnectionError { .. } => ErrorCategory::Connection,
StorageError::QueryError { .. } => ErrorCategory::Query,
StorageError::SerializationError { .. } | StorageError::DeserializationError { .. } => {
ErrorCategory::Serialization
}
StorageError::TransactionError { .. } => ErrorCategory::Transaction,
StorageError::ConstraintViolation { .. } => ErrorCategory::Constraint,
StorageError::NotFound { .. } => ErrorCategory::NotFound,
StorageError::AlreadyExists { .. } => ErrorCategory::Conflict,
StorageError::InvalidConfiguration { .. } => ErrorCategory::Configuration,
StorageError::Timeout { .. } => ErrorCategory::Timeout,
StorageError::InvalidState { .. } => ErrorCategory::State,
StorageError::LockError { .. } => ErrorCategory::Concurrency,
StorageError::MigrationError { .. } => ErrorCategory::Migration,
StorageError::UnsupportedOperation { .. } => ErrorCategory::Unsupported,
StorageError::InternalError { .. } => ErrorCategory::Internal,
StorageError::CapacityError { .. } => ErrorCategory::Capacity,
StorageError::IoError { .. } => ErrorCategory::Io,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorCategory {
Availability,
Connection,
Query,
Serialization,
Transaction,
Constraint,
NotFound,
Conflict,
Configuration,
Timeout,
State,
Concurrency,
Migration,
Unsupported,
Internal,
Capacity,
Io,
}
impl ErrorCategory {
pub fn is_client_error(&self) -> bool {
matches!(
self,
ErrorCategory::Query
| ErrorCategory::Constraint
| ErrorCategory::NotFound
| ErrorCategory::Conflict
| ErrorCategory::Configuration
| ErrorCategory::State
| ErrorCategory::Unsupported
)
}
pub fn is_server_error(&self) -> bool {
matches!(
self,
ErrorCategory::Availability
| ErrorCategory::Connection
| ErrorCategory::Transaction
| ErrorCategory::Timeout
| ErrorCategory::Concurrency
| ErrorCategory::Migration
| ErrorCategory::Internal
| ErrorCategory::Capacity
| ErrorCategory::Io
)
}
}