1use thiserror::Error;
2
3#[derive(Error, Debug)]
5pub enum RabbitError {
6 #[error("Connection error: {0}")]
7 Connection(#[from] lapin::Error),
8
9 #[error("Serialization error: {0}")]
10 Serialization(#[from] serde_json::Error),
11
12 #[error("Serialization error: {0}")]
13 SerializationError(String),
14
15 #[error("Configuration error: {0}")]
16 Configuration(String),
17
18 #[error("Channel error: {0}")]
19 ChannelError(String),
20
21 #[error("Consumer error: {0}")]
22 Consumer(String),
23
24 #[error("Publisher error: {0}")]
25 Publisher(String),
26
27 #[error("Retry exhausted: {0}")]
28 RetryExhausted(String),
29
30 #[error("Health check failed: {0}")]
31 HealthCheck(String),
32
33 #[error("Timeout error: {0}")]
34 Timeout(String),
35
36 #[error("IO error: {0}")]
37 Io(#[from] std::io::Error),
38
39 #[error("Generic error: {0}")]
40 Generic(#[from] anyhow::Error),
41}
42
43#[derive(Error, Debug)]
45pub enum RustRabbitError {
46 #[error("Rabbit error: {0}")]
48 Rabbit(#[from] RabbitError),
49
50 #[error("Request timeout")]
52 RequestTimeout,
53
54 #[error("Response channel closed")]
55 ResponseChannelClosed,
56
57 #[error("Saga not found")]
59 SagaNotFound,
60
61 #[error("Saga executor not found for action type: {0}")]
62 SagaExecutorNotFound(String),
63
64 #[error("Saga compensation failed")]
65 SagaCompensationFailed,
66
67 #[error("Event sequence error - events must be in order")]
69 EventSequenceError,
70
71 #[error("Unknown event type: {0}")]
72 UnknownEventType(String),
73
74 #[error("Aggregate not found")]
75 AggregateNotFound,
76
77 #[error("Snapshot creation failed")]
78 SnapshotCreationFailed,
79
80 #[error("Queue is full")]
82 QueueFull,
83
84 #[error("Queue not found: {0}")]
85 QueueNotFound(String),
86
87 #[error("Invalid priority value: {0}")]
88 InvalidPriority(u8),
89
90 #[error("Duplicate message detected")]
92 DuplicateMessage,
93
94 #[error("Deduplication store error: {0}")]
95 DeduplicationStore(String),
96
97 #[error("Channel send error")]
99 ChannelSendError,
100
101 #[error("Task join error: {0}")]
102 TaskJoinError(String),
103
104 #[error("Lock poisoned")]
105 LockPoisoned,
106}
107
108#[derive(Error, Debug, Clone)]
110pub enum ProcessingError {
111 #[error("Retryable error: {message}")]
113 Retryable {
114 message: String,
115 custom_delay: Option<std::time::Duration>,
117 },
118
119 #[error("Non-retryable error: {message}")]
121 NonRetryable {
122 message: String,
123 send_to_dlq: bool,
125 },
126}
127
128impl ProcessingError {
129 pub fn retryable<S: Into<String>>(message: S) -> Self {
131 Self::Retryable {
132 message: message.into(),
133 custom_delay: None,
134 }
135 }
136
137 pub fn retryable_with_delay<S: Into<String>>(message: S, delay: std::time::Duration) -> Self {
139 Self::Retryable {
140 message: message.into(),
141 custom_delay: Some(delay),
142 }
143 }
144
145 pub fn non_retryable<S: Into<String>>(message: S) -> Self {
147 Self::NonRetryable {
148 message: message.into(),
149 send_to_dlq: true,
150 }
151 }
152
153 pub fn discard<S: Into<String>>(message: S) -> Self {
155 Self::NonRetryable {
156 message: message.into(),
157 send_to_dlq: false,
158 }
159 }
160
161 pub fn is_retryable(&self) -> bool {
163 matches!(self, ProcessingError::Retryable { .. })
164 }
165
166 pub fn should_send_to_dlq(&self) -> bool {
168 match self {
169 ProcessingError::Retryable { .. } => false,
170 ProcessingError::NonRetryable { send_to_dlq, .. } => *send_to_dlq,
171 }
172 }
173
174 pub fn custom_delay(&self) -> Option<std::time::Duration> {
176 match self {
177 ProcessingError::Retryable { custom_delay, .. } => *custom_delay,
178 ProcessingError::NonRetryable { .. } => None,
179 }
180 }
181}
182
183pub type Result<T> = std::result::Result<T, RabbitError>;