Skip to main content

khive_storage/
error.rs

1//! Storage error types shared across all backend implementations.
2
3use std::borrow::Cow;
4use std::error::Error as StdError;
5
6use thiserror::Error;
7
8use crate::capability::StorageCapability;
9
10/// Unified error type for all storage operations.
11#[derive(Debug, Error)]
12pub enum StorageError {
13    #[error("{capability:?} resource not found: {resource} ({key})")]
14    NotFound {
15        capability: StorageCapability,
16        resource: &'static str,
17        key: String,
18    },
19
20    #[error("{capability:?} resource already exists: {resource} ({key})")]
21    AlreadyExists {
22        capability: StorageCapability,
23        resource: &'static str,
24        key: String,
25    },
26
27    #[error("conflict in {capability:?} during {operation}: {message}")]
28    Conflict {
29        capability: StorageCapability,
30        operation: Cow<'static, str>,
31        message: String,
32    },
33
34    #[error("invalid input for {capability:?} during {operation}: {message}")]
35    InvalidInput {
36        capability: StorageCapability,
37        operation: Cow<'static, str>,
38        message: String,
39    },
40
41    #[error("unsupported operation for {capability:?}: {operation} ({message})")]
42    Unsupported {
43        capability: StorageCapability,
44        operation: Cow<'static, str>,
45        message: String,
46    },
47
48    #[error("pool failure during {operation}: {message}")]
49    Pool {
50        operation: Cow<'static, str>,
51        message: String,
52    },
53
54    #[error("timeout during {operation}")]
55    Timeout { operation: Cow<'static, str> },
56
57    #[error("sql transaction failure during {operation}: {message}")]
58    Transaction {
59        operation: Cow<'static, str>,
60        message: String,
61    },
62
63    #[error("serialization failure in {capability:?}: {message}")]
64    Serialization {
65        capability: StorageCapability,
66        message: String,
67    },
68
69    #[error("index maintenance failure in {capability:?}: {message}")]
70    IndexMaintenance {
71        capability: StorageCapability,
72        message: String,
73    },
74
75    #[error("backend driver error in {capability:?} during {operation}: {source}")]
76    Driver {
77        capability: StorageCapability,
78        operation: Cow<'static, str>,
79        #[source]
80        source: Box<dyn StdError + Send + Sync>,
81    },
82}
83
84impl StorageError {
85    pub fn driver(
86        capability: StorageCapability,
87        operation: impl Into<Cow<'static, str>>,
88        source: impl StdError + Send + Sync + 'static,
89    ) -> Self {
90        Self::Driver {
91            capability,
92            operation: operation.into(),
93            source: Box::new(source),
94        }
95    }
96
97    pub fn capability(&self) -> Option<StorageCapability> {
98        match self {
99            Self::NotFound { capability, .. }
100            | Self::AlreadyExists { capability, .. }
101            | Self::Conflict { capability, .. }
102            | Self::InvalidInput { capability, .. }
103            | Self::Unsupported { capability, .. }
104            | Self::Serialization { capability, .. }
105            | Self::IndexMaintenance { capability, .. }
106            | Self::Driver { capability, .. } => Some(*capability),
107            Self::Pool { .. } | Self::Timeout { .. } | Self::Transaction { .. } => None,
108        }
109    }
110
111    pub fn is_retryable(&self) -> bool {
112        matches!(
113            self,
114            Self::Pool { .. } | Self::Timeout { .. } | Self::Transaction { .. }
115        )
116    }
117}