1use std::io;
2use thiserror::Error;
3
4#[derive(Error, Debug)]
5pub enum AzothError {
6 #[error("IO error: {0}")]
7 Io(#[from] io::Error),
8
9 #[error("Serialization error: {0}")]
10 Serialization(String),
11
12 #[error("Transaction error: {0}")]
13 Transaction(String),
14
15 #[error("Store is sealed at event {0}")]
16 Sealed(u64),
17
18 #[error("Store is paused, ingestion suspended")]
19 Paused,
20
21 #[error("Configuration error: {0}")]
22 Config(String),
23
24 #[error("Backup error: {0}")]
25 Backup(String),
26
27 #[error("Restore error: {0}")]
28 Restore(String),
29
30 #[error("Encryption error: {0}")]
31 Encryption(String),
32
33 #[error("Projection error: {0}")]
34 Projection(String),
35
36 #[error("Event decoding error: {0}")]
37 EventDecode(String),
38
39 #[error("Preflight validation error: {0}")]
40 PreflightFailed(String),
41
42 #[error("Lock error: {0}")]
43 Lock(String),
44
45 #[error("Not found: {0}")]
46 NotFound(String),
47
48 #[error("Invalid state: {0}")]
49 InvalidState(String),
50
51 #[error("Timeout: {0}")]
52 Timeout(String),
53
54 #[error(
55 "Lock acquisition timed out after {timeout_ms}ms (possible deadlock or high contention)"
56 )]
57 LockTimeout { timeout_ms: u64 },
58
59 #[error("Attempted to access undeclared key '{key}' - all keys must be declared via keys() before access")]
60 UndeclaredKeyAccess { key: String },
61
62 #[error("Circuit breaker is open, rejecting request")]
63 CircuitBreakerOpen,
64
65 #[error("Event log write failed after state commit (events saved to dead letter queue): {0}")]
66 EventLogWriteFailed(String),
67
68 #[error("Key too large ({size} bytes, max {max}): {context}")]
69 KeyTooLarge {
70 size: usize,
71 max: usize,
72 context: String,
73 },
74
75 #[error("Value too large ({size} bytes, max {max}): {context}")]
76 ValueTooLarge {
77 size: usize,
78 max: usize,
79 context: String,
80 },
81
82 #[error("Internal error: {0}")]
83 Internal(String),
84
85 #[error("Other error: {0}")]
86 Other(#[from] anyhow::Error),
87}
88
89pub type Result<T> = std::result::Result<T, AzothError>;
90
91impl AzothError {
92 pub fn context(self, msg: impl Into<String>) -> Self {
103 let ctx = msg.into();
104 AzothError::Internal(format!("{}: {}", ctx, self))
105 }
106}
107
108pub trait ResultExt<T> {
112 fn context(self, msg: impl Into<String>) -> Result<T>;
114
115 fn with_context<F: FnOnce() -> String>(self, f: F) -> Result<T>;
117}
118
119impl<T> ResultExt<T> for Result<T> {
120 fn context(self, msg: impl Into<String>) -> Result<T> {
121 self.map_err(|e| e.context(msg))
122 }
123
124 fn with_context<F: FnOnce() -> String>(self, f: F) -> Result<T> {
125 self.map_err(|e| e.context(f()))
126 }
127}
128
129