1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, StorageError>;
7
8#[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}