Skip to main content

tokio_events/
error.rs

1//! Error types for the tokio-events library.
2
3use std::fmt;
4use thiserror::Error;
5use uuid::Uuid;
6
7/// Type alias for Results in this crate
8pub type Result<T> = std::result::Result<T, Error>;
9
10/// Main error type for tokio-events
11#[derive(Error, Debug)]
12pub enum Error {
13    /// Event publishing failed
14    #[error("Failed to publish event: {0}")]
15    PublishError(String),
16
17    /// Subscription failed
18    #[error("Failed to subscribe: {0}")]
19    SubscriptionError(String),
20
21    /// Event not found in registry
22    #[error("Event type not registered: {type_name}")]
23    EventNotRegistered {
24        /// The name of the event type that was not registered
25        type_name: String,
26    },
27
28    /// Subscription not found
29    #[error("Subscription not found: {id}")]
30    SubscriptionNotFound {
31        /// The unique identifier of the subscription that was not found
32        id: Uuid,
33    },
34
35    /// Event handler error
36    #[error("Handler error: {0}")]
37    HandlerError(String),
38
39    /// Event bus is shutting down
40    #[error("Event bus is shutting down")]
41    ShuttingDown,
42
43    /// Channel send error
44    #[error("Failed to send through channel")]
45    ChannelSendError,
46
47    /// Channel receive error
48    #[error("Failed to receive from channel")]
49    ChannelReceiveError,
50
51    /// Serialization error
52    #[error("Serialization error: {0}")]
53    SerializationError(String),
54
55    /// Configuration error
56    #[error("Configuration error: {0}")]
57    ConfigError(String),
58
59    /// Generic internal error
60    #[error("Internal error: {0}")]
61    Internal(String),
62}
63
64impl Error {
65    /// Create a new internal error with a custom message
66    pub fn internal(msg: impl Into<String>) -> Self {
67        Error::Internal(msg.into())
68    }
69
70    /// Create a new handler error
71    pub fn handler(msg: impl Into<String>) -> Self {
72        Error::HandlerError(msg.into())
73    }
74
75    /// Check if this error indicates the system is shutting down
76    pub fn is_shutdown(&self) -> bool {
77        matches!(self, Error::ShuttingDown)
78    }
79
80    /// Check if this is a channel-related error
81    pub fn is_channel_error(&self) -> bool {
82        matches!(self, Error::ChannelSendError | Error::ChannelReceiveError)
83    }
84}
85
86/// Error context for debugging
87#[derive(Debug)]
88pub struct ErrorContext {
89    /// The unique identifier of the event, if available
90    pub event_id: Option<Uuid>,
91    /// The type name of the event, if available
92    pub event_type: Option<String>,
93    /// The name of the handler, if available
94    pub handler_name: Option<String>,
95    /// The timestamp when the error context was created
96    pub timestamp: chrono::DateTime<chrono::Utc>,
97}
98
99impl Default for ErrorContext {
100    fn default() -> Self {
101        Self::new()
102    }
103}
104
105impl ErrorContext {
106    /// Create a new error context
107    pub fn new() -> Self {
108        Self {
109            event_id: None,
110            event_type: None,
111            handler_name: None,
112            timestamp: chrono::Utc::now(),
113        }
114    }
115
116    /// Set the event ID
117    pub fn with_event_id(mut self, id: Uuid) -> Self {
118        self.event_id = Some(id);
119        self
120    }
121
122    /// Set the event type
123    pub fn with_event_type(mut self, event_type: impl Into<String>) -> Self {
124        self.event_type = Some(event_type.into());
125        self
126    }
127
128    /// Set the handler name
129    pub fn with_handler(mut self, name: impl Into<String>) -> Self {
130        self.handler_name = Some(name.into());
131        self
132    }
133}
134
135impl fmt::Display for ErrorContext {
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        write!(f, "Error at {}", self.timestamp)?;
138        if let Some(id) = &self.event_id {
139            write!(f, " [event_id: {}]", id)?;
140        }
141        if let Some(event_type) = &self.event_type {
142            write!(f, " [type: {}]", event_type)?;
143        }
144        if let Some(handler) = &self.handler_name {
145            write!(f, " [handler: {}]", handler)?;
146        }
147        Ok(())
148    }
149}
150
151#[cfg(test)]
152mod tests {
153    use super::*;
154
155    #[test]
156    fn test_error_display() {
157        let err = Error::PublishError("test error".to_string());
158        assert_eq!(err.to_string(), "Failed to publish event: test error");
159    }
160
161    #[test]
162    fn test_error_is_shutdown() {
163        assert!(Error::ShuttingDown.is_shutdown());
164        assert!(!Error::internal("test").is_shutdown());
165    }
166
167    #[test]
168    fn test_error_context() {
169        let ctx = ErrorContext::new()
170            .with_event_id(Uuid::max())
171            .with_event_type("TestEvent")
172            .with_handler("test_handler");
173
174        let display = ctx.to_string();
175        assert!(display.contains("TestEvent"));
176        assert!(display.contains("test_handler"));
177    }
178}