Skip to main content

queue_runtime/
error.rs

1//! Error types for queue operations.
2
3use crate::message::Timestamp;
4use chrono::Duration;
5use thiserror::Error;
6
7/// Comprehensive error type for all queue operations
8#[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    /// Check if error is transient and should be retried
62    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, // Provider-specific errors are usually transient
75            Self::SerializationError(_) => false,
76            Self::ConfigurationError(_) => false,
77            Self::ValidationError(_) => false,
78        }
79    }
80
81    /// Check if error should be retried
82    pub fn should_retry(&self) -> bool {
83        self.is_transient()
84    }
85
86    /// Get suggested retry delay
87    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/// Errors during message serialization/deserialization
98#[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/// Configuration errors
114#[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/// Validation errors
130#[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;