rust_rabbit/
error.rs

1use thiserror::Error;
2
3/// Main error type for the rust-rabbit library
4#[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/// Extended error type for advanced patterns (Phase 2)
44#[derive(Error, Debug)]
45pub enum RustRabbitError {
46    // Core errors
47    #[error("Rabbit error: {0}")]
48    Rabbit(#[from] RabbitError),
49
50    // Request-Response pattern errors
51    #[error("Request timeout")]
52    RequestTimeout,
53
54    #[error("Response channel closed")]
55    ResponseChannelClosed,
56
57    // Saga pattern errors
58    #[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    // Event sourcing errors
68    #[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    // Priority queue errors
81    #[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    // Deduplication errors
91    #[error("Duplicate message detected")]
92    DuplicateMessage,
93
94    #[error("Deduplication store error: {0}")]
95    DeduplicationStore(String),
96
97    // General async errors
98    #[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/// Processing error types for consumer handlers
109#[derive(Error, Debug, Clone)]
110pub enum ProcessingError {
111    /// Retryable error - message should be retried with delay
112    #[error("Retryable error: {message}")]
113    Retryable {
114        message: String,
115        /// Optional custom retry delay override
116        custom_delay: Option<std::time::Duration>,
117    },
118
119    /// Non-retryable error - message should be rejected permanently
120    #[error("Non-retryable error: {message}")]
121    NonRetryable {
122        message: String,
123        /// Whether to send to dead letter queue (default: true)
124        send_to_dlq: bool,
125    },
126}
127
128impl ProcessingError {
129    /// Create a retryable error with default delay
130    pub fn retryable<S: Into<String>>(message: S) -> Self {
131        Self::Retryable {
132            message: message.into(),
133            custom_delay: None,
134        }
135    }
136
137    /// Create a retryable error with custom delay
138    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    /// Create a non-retryable error (will be sent to DLQ)
146    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    /// Create a non-retryable error that should be discarded (not sent to DLQ)
154    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    /// Check if this error is retryable
162    pub fn is_retryable(&self) -> bool {
163        matches!(self, ProcessingError::Retryable { .. })
164    }
165
166    /// Check if this error should be sent to DLQ
167    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    /// Get custom delay if specified
175    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
183/// Result type alias for the rust-rabbit library
184pub type Result<T> = std::result::Result<T, RabbitError>;