1use thiserror::Error;
6
7pub type Result<T> = std::result::Result<T, MemoryError>;
9
10#[derive(Error, Debug)]
12pub enum MemoryError {
13 #[error("Database error: {0}")]
15 Database(#[from] sqlx::Error),
16
17 #[error("Serialization error: {0}")]
19 Serialization(#[from] serde_json::Error),
20
21 #[error("IO error: {0}")]
23 Io(#[from] std::io::Error),
24
25 #[error("Configuration error: {0}")]
27 Config(#[from] config::ConfigError),
28
29 #[error("Memory with id '{id}' not found")]
31 MemoryNotFound { id: String },
32
33 #[error("Invalid vector dimension: expected {expected}, got {actual}")]
35 InvalidVectorDimension { expected: usize, actual: usize },
36
37 #[error("Invalid query parameter: {message}")]
39 InvalidQuery { message: String },
40
41 #[error("Failed to create connection between memories '{from}' and '{to}': {reason}")]
43 ConnectionFailed {
44 from: String,
45 to: String,
46 reason: String,
47 },
48
49 #[error("Memory evolution failed: {message}")]
51 EvolutionFailed { message: String },
52
53 #[error("Learning module error: {message}")]
55 LearningError { message: String },
56
57 #[error("Retrieval engine error: {message}")]
59 RetrievalError { message: String },
60
61 #[error("Vector operation error: {message}")]
63 VectorError { message: String },
64
65 #[error("Graph operation error: {message}")]
67 GraphError { message: String },
68
69 #[error("Cache error: {message}")]
71 CacheError { message: String },
72
73 #[error("Concurrency error: {message}")]
75 ConcurrencyError { message: String },
76
77 #[error("Insufficient resources: {message}")]
79 InsufficientResources { message: String },
80
81 #[error("Operation timed out: {operation}")]
83 Timeout { operation: String },
84
85 #[error("Validation error: {message}")]
87 ValidationError { message: String },
88
89 #[error("Permission denied: {message}")]
91 PermissionDenied { message: String },
92
93 #[error("Internal error: {message}")]
95 Internal { message: String },
96
97 #[error("Other error: {0}")]
99 Other(#[from] anyhow::Error),
100}
101
102impl MemoryError {
103 pub fn memory_not_found(id: impl Into<String>) -> Self {
105 Self::MemoryNotFound { id: id.into() }
106 }
107
108 pub fn invalid_vector_dimension(expected: usize, actual: usize) -> Self {
110 Self::InvalidVectorDimension { expected, actual }
111 }
112
113 pub fn invalid_query(message: impl Into<String>) -> Self {
115 Self::InvalidQuery {
116 message: message.into(),
117 }
118 }
119
120 pub fn connection_failed(
122 from: impl Into<String>,
123 to: impl Into<String>,
124 reason: impl Into<String>,
125 ) -> Self {
126 Self::ConnectionFailed {
127 from: from.into(),
128 to: to.into(),
129 reason: reason.into(),
130 }
131 }
132
133 pub fn evolution_failed(message: impl Into<String>) -> Self {
135 Self::EvolutionFailed {
136 message: message.into(),
137 }
138 }
139
140 pub fn learning_error(message: impl Into<String>) -> Self {
142 Self::LearningError {
143 message: message.into(),
144 }
145 }
146
147 pub fn retrieval_error(message: impl Into<String>) -> Self {
149 Self::RetrievalError {
150 message: message.into(),
151 }
152 }
153
154 pub fn vector_error(message: impl Into<String>) -> Self {
156 Self::VectorError {
157 message: message.into(),
158 }
159 }
160
161 pub fn graph_error(message: impl Into<String>) -> Self {
163 Self::GraphError {
164 message: message.into(),
165 }
166 }
167
168 pub fn cache_error(message: impl Into<String>) -> Self {
170 Self::CacheError {
171 message: message.into(),
172 }
173 }
174
175 pub fn concurrency_error(message: impl Into<String>) -> Self {
177 Self::ConcurrencyError {
178 message: message.into(),
179 }
180 }
181
182 pub fn insufficient_resources(message: impl Into<String>) -> Self {
184 Self::InsufficientResources {
185 message: message.into(),
186 }
187 }
188
189 pub fn timeout(operation: impl Into<String>) -> Self {
191 Self::Timeout {
192 operation: operation.into(),
193 }
194 }
195
196 pub fn validation_error(message: impl Into<String>) -> Self {
198 Self::ValidationError {
199 message: message.into(),
200 }
201 }
202
203 pub fn permission_denied(message: impl Into<String>) -> Self {
205 Self::PermissionDenied {
206 message: message.into(),
207 }
208 }
209
210 pub fn internal(message: impl Into<String>) -> Self {
212 Self::Internal {
213 message: message.into(),
214 }
215 }
216
217 pub fn is_database_error(&self) -> bool {
219 matches!(self, Self::Database(_))
220 }
221
222 pub fn is_serialization_error(&self) -> bool {
224 matches!(self, Self::Serialization(_))
225 }
226
227 pub fn is_memory_not_found(&self) -> bool {
229 matches!(self, Self::MemoryNotFound { .. })
230 }
231
232 pub fn is_timeout(&self) -> bool {
234 matches!(self, Self::Timeout { .. })
235 }
236
237 pub fn severity(&self) -> ErrorSeverity {
239 match self {
240 Self::Database(_) | Self::Io(_) => ErrorSeverity::Critical,
241 Self::MemoryNotFound { .. }
242 | Self::InvalidQuery { .. }
243 | Self::ValidationError { .. } => ErrorSeverity::Warning,
244 Self::Timeout { .. } | Self::InsufficientResources { .. } => ErrorSeverity::Error,
245 Self::Internal { .. } => ErrorSeverity::Critical,
246 _ => ErrorSeverity::Error,
247 }
248 }
249}
250
251#[derive(Debug, Clone, Copy, PartialEq, Eq)]
253pub enum ErrorSeverity {
254 Info,
256 Warning,
258 Error,
260 Critical,
262}
263
264impl std::fmt::Display for ErrorSeverity {
265 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266 match self {
267 Self::Info => write!(f, "INFO"),
268 Self::Warning => write!(f, "WARNING"),
269 Self::Error => write!(f, "ERROR"),
270 Self::Critical => write!(f, "CRITICAL"),
271 }
272 }
273}
274
275#[derive(Debug, Clone)]
277pub struct ErrorContext {
278 pub operation: String,
279 pub component: String,
280 pub timestamp: chrono::DateTime<chrono::Utc>,
281 pub additional_info: std::collections::HashMap<String, String>,
282}
283
284impl ErrorContext {
285 pub fn new(operation: impl Into<String>, component: impl Into<String>) -> Self {
287 Self {
288 operation: operation.into(),
289 component: component.into(),
290 timestamp: chrono::Utc::now(),
291 additional_info: std::collections::HashMap::new(),
292 }
293 }
294
295 pub fn with_info(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
297 self.additional_info.insert(key.into(), value.into());
298 self
299 }
300}
301
302#[cfg(test)]
303mod tests {
304 use super::*;
305
306 #[test]
307 fn test_error_creation() {
308 let error = MemoryError::memory_not_found("test_id");
309 assert!(error.is_memory_not_found());
310 assert_eq!(error.severity(), ErrorSeverity::Warning);
311 }
312
313 #[test]
314 fn test_error_context() {
315 let context = ErrorContext::new("test_operation", "test_component")
316 .with_info("key1", "value1")
317 .with_info("key2", "value2");
318
319 assert_eq!(context.operation, "test_operation");
320 assert_eq!(context.component, "test_component");
321 assert_eq!(context.additional_info.len(), 2);
322 }
323
324 #[test]
325 fn test_error_severity() {
326 assert_eq!(ErrorSeverity::Critical.to_string(), "CRITICAL");
327 assert_eq!(ErrorSeverity::Error.to_string(), "ERROR");
328 assert_eq!(ErrorSeverity::Warning.to_string(), "WARNING");
329 assert_eq!(ErrorSeverity::Info.to_string(), "INFO");
330 }
331}