Skip to main content

otelite_storage/
error.rs

1//! Internal error type for the SQLite storage backend.
2
3use thiserror::Error;
4
5/// Result type for internal SQLite operations.
6pub type Result<T> = std::result::Result<T, StorageError>;
7
8/// SQLite-specific error type with `#[from]` conversions for database-layer errors.
9///
10/// This type is an implementation detail of `otelite-storage`.  External callers
11/// should use `otelite_core::storage::StorageError` (re-exported as
12/// `otelite_storage::StorageError`).  The `From` impl below converts between
13/// the two at the `StorageBackend` trait boundary.
14#[derive(Error, Debug)]
15pub enum StorageError {
16    #[error("Failed to initialize storage: {0}")]
17    InitializationError(String),
18
19    #[error("Failed to write data: {0}")]
20    WriteError(String),
21
22    #[error("Failed to query data: {0}")]
23    QueryError(String),
24
25    #[error("Insufficient disk space: {0}")]
26    DiskFullError(String),
27
28    #[error("Storage corruption detected: {0}")]
29    CorruptionError(String),
30
31    #[error("Permission denied: {0}")]
32    PermissionError(String),
33
34    #[error("Configuration error: {0}")]
35    ConfigError(String),
36
37    #[error("Purge operation failed: {0}")]
38    PurgeError(String),
39
40    #[error("Database error: {0}")]
41    DatabaseError(#[from] rusqlite::Error),
42
43    #[error("I/O error: {0}")]
44    IoError(#[from] std::io::Error),
45
46    #[error("Serialization error: {0}")]
47    SerializationError(#[from] serde_json::Error),
48}
49
50impl StorageError {
51    pub fn is_recoverable(&self) -> bool {
52        matches!(
53            self,
54            StorageError::WriteError(_) | StorageError::QueryError(_) | StorageError::PurgeError(_)
55        )
56    }
57
58    pub fn is_corruption(&self) -> bool {
59        matches!(self, StorageError::CorruptionError(_))
60    }
61
62    pub fn is_disk_full(&self) -> bool {
63        matches!(self, StorageError::DiskFullError(_))
64    }
65}
66
67impl From<StorageError> for otelite_core::storage::StorageError {
68    fn from(e: StorageError) -> Self {
69        match e {
70            StorageError::InitializationError(s) => Self::InitializationError(s),
71            StorageError::WriteError(s) => Self::WriteError(s),
72            StorageError::QueryError(s) => Self::QueryError(s),
73            StorageError::DiskFullError(s) => Self::DiskFullError(s),
74            StorageError::CorruptionError(s) => Self::CorruptionError(s),
75            StorageError::PermissionError(s) => Self::PermissionError(s),
76            StorageError::ConfigError(s) => Self::ConfigError(s),
77            StorageError::PurgeError(s) => Self::PurgeError(s),
78            StorageError::DatabaseError(e) => Self::DatabaseError(e.to_string()),
79            StorageError::IoError(e) => Self::IoError(e.to_string()),
80            StorageError::SerializationError(e) => Self::SerializationError(e.to_string()),
81        }
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn test_error_display() {
91        let err = StorageError::InitializationError("test error".to_string());
92        assert_eq!(err.to_string(), "Failed to initialize storage: test error");
93    }
94
95    #[test]
96    fn test_error_recoverable() {
97        let err = StorageError::WriteError("test".to_string());
98        assert!(err.is_recoverable());
99
100        let err = StorageError::CorruptionError("test".to_string());
101        assert!(!err.is_recoverable());
102    }
103
104    #[test]
105    fn test_error_corruption_check() {
106        let err = StorageError::CorruptionError("test".to_string());
107        assert!(err.is_corruption());
108
109        let err = StorageError::WriteError("test".to_string());
110        assert!(!err.is_corruption());
111    }
112
113    #[test]
114    fn test_error_disk_full_check() {
115        let err = StorageError::DiskFullError("test".to_string());
116        assert!(err.is_disk_full());
117
118        let err = StorageError::WriteError("test".to_string());
119        assert!(!err.is_disk_full());
120    }
121}