1use thiserror::Error;
4
5#[derive(Debug, Error)]
7pub enum EventError {
8 #[error("Connection error: {0}")]
10 Connection(String),
11
12 #[error("Provider error: {0}")]
14 JetStream(String),
15
16 #[error("Failed to publish event to subject '{subject}': {reason}")]
18 Publish {
19 subject: String,
20 reason: String,
21 },
22
23 #[error("Failed to subscribe to subject '{subject}': {reason}")]
25 Subscribe {
26 subject: String,
27 reason: String,
28 },
29
30 #[error("Serialization error: {0}")]
32 Serialization(#[from] serde_json::Error),
33
34 #[error("Event not found: {0}")]
36 NotFound(String),
37
38 #[error("Configuration error: {0}")]
40 Config(String),
41
42 #[error("Stream error: {0}")]
44 Stream(String),
45
46 #[error("Consumer error: {0}")]
48 Consumer(String),
49
50 #[error("Failed to acknowledge message: {0}")]
52 Ack(String),
53
54 #[error("Operation timed out: {0}")]
56 Timeout(String),
57
58 #[error("Provider error: {0}")]
60 Provider(String),
61
62 #[error("Schema validation failed for event type '{event_type}' v{version}: {reason}")]
64 SchemaValidation {
65 event_type: String,
66 version: u32,
67 reason: String,
68 },
69
70 #[error("Sink delivery failed for '{sink}': {reason}")]
72 SinkDelivery {
73 sink: String,
74 reason: String,
75 },
76
77 #[error("Broker routing error: {0}")]
79 BrokerRouting(String),
80
81 #[error("CloudEvent conversion error: {0}")]
83 CloudEventConversion(String),
84
85 #[error("Event source error: {0}")]
87 Source(String),
88}
89
90pub type Result<T> = std::result::Result<T, EventError>;
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn test_connection_error_display() {
99 let err = EventError::Connection("refused".to_string());
100 assert_eq!(err.to_string(), "Connection error: refused");
101 }
102
103 #[test]
104 fn test_publish_error_display() {
105 let err = EventError::Publish {
106 subject: "events.test.a".to_string(),
107 reason: "timeout".to_string(),
108 };
109 assert!(err.to_string().contains("events.test.a"));
110 assert!(err.to_string().contains("timeout"));
111 }
112
113 #[test]
114 fn test_subscribe_error_display() {
115 let err = EventError::Subscribe {
116 subject: "events.market.>".to_string(),
117 reason: "consumer limit".to_string(),
118 };
119 assert!(err.to_string().contains("events.market.>"));
120 }
121
122 #[test]
123 fn test_schema_validation_error_display() {
124 let err = EventError::SchemaValidation {
125 event_type: "forex.rate".to_string(),
126 version: 2,
127 reason: "Missing required field 'rate'".to_string(),
128 };
129 let msg = err.to_string();
130 assert!(msg.contains("forex.rate"));
131 assert!(msg.contains("v2"));
132 assert!(msg.contains("rate"));
133 }
134
135 #[test]
136 fn test_not_found_error() {
137 let err = EventError::NotFound("sub-123".to_string());
138 assert!(err.to_string().contains("sub-123"));
139 }
140
141 #[test]
142 fn test_timeout_error() {
143 let err = EventError::Timeout("publish ack".to_string());
144 assert!(err.to_string().contains("publish ack"));
145 }
146
147 #[test]
148 fn test_serialization_error_from() {
149 let json_err = serde_json::from_str::<String>("invalid").unwrap_err();
150 let err: EventError = json_err.into();
151 assert!(matches!(err, EventError::Serialization(_)));
152 }
153
154 #[test]
155 fn test_sink_delivery_error() {
156 let err = EventError::SinkDelivery {
157 sink: "http-sink".to_string(),
158 reason: "connection refused".to_string(),
159 };
160 let msg = err.to_string();
161 assert!(msg.contains("http-sink"));
162 assert!(msg.contains("connection refused"));
163 }
164
165 #[test]
166 fn test_broker_routing_error() {
167 let err = EventError::BrokerRouting("no matching triggers".to_string());
168 assert!(err.to_string().contains("no matching triggers"));
169 }
170
171 #[test]
172 fn test_cloudevent_conversion_error() {
173 let err = EventError::CloudEventConversion("missing required field".to_string());
174 assert!(err.to_string().contains("missing required field"));
175 }
176
177 #[test]
178 fn test_source_error() {
179 let err = EventError::Source("interval too small".to_string());
180 assert!(err.to_string().contains("interval too small"));
181 }
182}