1use crate::message::Timestamp;
4use chrono::Duration;
5use thiserror::Error;
6
7#[derive(Debug, Error)]
9pub enum QueueError {
10 #[error("Queue not found: {queue_name}")]
11 QueueNotFound { queue_name: String },
12
13 #[error("Message not found or receipt expired: {receipt}")]
14 MessageNotFound { receipt: String },
15
16 #[error("Session '{session_id}' is locked until {locked_until}")]
17 SessionLocked {
18 session_id: String,
19 locked_until: Timestamp,
20 },
21
22 #[error("Session '{session_id}' not found or expired")]
23 SessionNotFound { session_id: String },
24
25 #[error("Operation timed out after {duration:?}")]
26 Timeout { duration: Duration },
27
28 #[error("Connection failed: {message}")]
29 ConnectionFailed { message: String },
30
31 #[error("Authentication failed: {message}")]
32 AuthenticationFailed { message: String },
33
34 #[error("Permission denied for operation: {operation}")]
35 PermissionDenied { operation: String },
36
37 #[error("Message too large: {size} bytes (max: {max_size})")]
38 MessageTooLarge { size: usize, max_size: usize },
39
40 #[error("Batch size {size} exceeds maximum {max_size}")]
41 BatchTooLarge { size: usize, max_size: usize },
42
43 #[error("Provider error ({provider}): {code} - {message}")]
44 ProviderError {
45 provider: String,
46 code: String,
47 message: String,
48 },
49
50 #[error("Serialization failed: {0}")]
51 SerializationError(#[from] SerializationError),
52
53 #[error("Configuration error: {0}")]
54 ConfigurationError(#[from] ConfigurationError),
55
56 #[error("Validation error: {0}")]
57 ValidationError(#[from] ValidationError),
58}
59
60impl QueueError {
61 pub fn is_transient(&self) -> bool {
63 match self {
64 Self::QueueNotFound { .. } => false,
65 Self::MessageNotFound { .. } => false,
66 Self::SessionLocked { .. } => true,
67 Self::SessionNotFound { .. } => false,
68 Self::Timeout { .. } => true,
69 Self::ConnectionFailed { .. } => true,
70 Self::AuthenticationFailed { .. } => false,
71 Self::PermissionDenied { .. } => false,
72 Self::MessageTooLarge { .. } => false,
73 Self::BatchTooLarge { .. } => false,
74 Self::ProviderError { .. } => true, Self::SerializationError(_) => false,
76 Self::ConfigurationError(_) => false,
77 Self::ValidationError(_) => false,
78 }
79 }
80
81 pub fn should_retry(&self) -> bool {
83 self.is_transient()
84 }
85
86 pub fn retry_after(&self) -> Option<Duration> {
88 match self {
89 Self::SessionLocked { .. } => Some(Duration::seconds(5)),
90 Self::Timeout { .. } => Some(Duration::seconds(1)),
91 Self::ConnectionFailed { .. } => Some(Duration::seconds(5)),
92 _ => None,
93 }
94 }
95}
96
97#[derive(Debug, Error)]
99pub enum SerializationError {
100 #[error("JSON serialization failed: {0}")]
101 JsonError(#[from] serde_json::Error),
102
103 #[error("Message body is not valid UTF-8")]
104 InvalidUtf8,
105
106 #[error("Message attribute '{key}' has invalid value")]
107 InvalidAttribute { key: String },
108
109 #[error("Message exceeds size limit: {size} bytes")]
110 MessageTooLarge { size: usize },
111}
112
113#[derive(Debug, Error)]
115pub enum ConfigurationError {
116 #[error("Invalid configuration: {message}")]
117 Invalid { message: String },
118
119 #[error("Missing required configuration: {key}")]
120 Missing { key: String },
121
122 #[error("Configuration parsing failed: {message}")]
123 Parsing { message: String },
124
125 #[error("Unsupported provider: {provider} - {message}")]
126 UnsupportedProvider { provider: String, message: String },
127}
128
129#[derive(Debug, Error)]
131pub enum ValidationError {
132 #[error("Required field missing: {field}")]
133 Required { field: String },
134
135 #[error("Invalid format for {field}: {message}")]
136 InvalidFormat { field: String, message: String },
137
138 #[error("Value out of range for {field}: {message}")]
139 OutOfRange { field: String, message: String },
140}
141
142#[cfg(test)]
143#[path = "error_tests.rs"]
144mod tests;