backbone_messaging/
bus.rs1use std::collections::HashMap;
4use std::sync::Arc;
5use tokio::sync::{broadcast, RwLock};
6use chrono::{DateTime, Utc};
7
8use crate::{DomainEvent, EventEnvelope, EventError, EventHandler};
9
10type HandlerMap<E> = Arc<RwLock<HashMap<String, Vec<Arc<dyn EventHandler<E>>>>>>;
12
13#[derive(Debug, Clone)]
15pub struct EventBusConfig {
16 pub buffer_size: usize,
18 pub persist_events: bool,
20 pub retention_seconds: u64,
22 pub max_history_size: usize,
24}
25
26impl Default for EventBusConfig {
27 fn default() -> Self {
28 Self {
29 buffer_size: 1000,
30 persist_events: false,
31 retention_seconds: 86400, max_history_size: 10000,
33 }
34 }
35}
36
37impl EventBusConfig {
38 pub fn with_persistence() -> Self {
40 Self {
41 persist_events: true,
42 ..Default::default()
43 }
44 }
45
46 pub fn buffer_size(mut self, size: usize) -> Self {
48 self.buffer_size = size;
49 self
50 }
51
52 pub fn retention_seconds(mut self, seconds: u64) -> Self {
54 self.retention_seconds = seconds;
55 self
56 }
57}
58
59pub struct EventBus<E: DomainEvent> {
88 sender: broadcast::Sender<EventEnvelope<E>>,
90 config: EventBusConfig,
92 handlers: HandlerMap<E>,
94 history: Arc<RwLock<Vec<EventEnvelope<E>>>>,
96}
97
98impl<E: DomainEvent> EventBus<E> {
99 pub fn new() -> Self {
101 Self::with_config(EventBusConfig::default())
102 }
103
104 pub fn with_config(config: EventBusConfig) -> Self {
106 let (sender, _) = broadcast::channel(config.buffer_size);
107 Self {
108 sender,
109 config,
110 handlers: Arc::new(RwLock::new(HashMap::new())),
111 history: Arc::new(RwLock::new(Vec::new())),
112 }
113 }
114
115 pub async fn publish(&self, event: E) -> Result<(), EventError> {
117 let envelope = EventEnvelope::new(event);
118 self.publish_envelope(envelope).await
119 }
120
121 pub async fn publish_all(&self, events: Vec<E>) -> Result<(), EventError> {
123 for event in events {
124 self.publish(event).await?;
125 }
126 Ok(())
127 }
128
129 pub async fn publish_envelope(&self, envelope: EventEnvelope<E>) -> Result<(), EventError> {
131 if self.config.persist_events {
133 self.store_event(&envelope).await;
134 }
135
136 let _ = self.sender.send(envelope.clone());
138
139 self.dispatch(envelope).await?;
141
142 Ok(())
143 }
144
145 pub async fn register_handler(&self, handler: Arc<dyn EventHandler<E>>) {
147 let event_types = handler.event_types();
148 let mut handlers = self.handlers.write().await;
149
150 if event_types.is_empty() {
151 handlers
153 .entry("*".to_string())
154 .or_default()
155 .push(Arc::clone(&handler));
156 } else {
157 for event_type in event_types {
158 handlers
159 .entry(event_type.to_string())
160 .or_default()
161 .push(Arc::clone(&handler));
162 }
163 }
164 }
165
166 pub fn subscribe(&self) -> broadcast::Receiver<EventEnvelope<E>> {
168 self.sender.subscribe()
169 }
170
171 pub async fn history(&self) -> Vec<EventEnvelope<E>> {
173 self.history.read().await.clone()
174 }
175
176 pub async fn events_for_aggregate(&self, aggregate_id: &str) -> Vec<EventEnvelope<E>> {
178 self.history
179 .read()
180 .await
181 .iter()
182 .filter(|e| e.aggregate_id == aggregate_id)
183 .cloned()
184 .collect()
185 }
186
187 pub async fn events_by_type(&self, event_type: &str) -> Vec<EventEnvelope<E>> {
189 self.history
190 .read()
191 .await
192 .iter()
193 .filter(|e| e.event_type == event_type)
194 .cloned()
195 .collect()
196 }
197
198 pub async fn events_in_range(
200 &self,
201 start: DateTime<Utc>,
202 end: DateTime<Utc>,
203 ) -> Vec<EventEnvelope<E>> {
204 self.history
205 .read()
206 .await
207 .iter()
208 .filter(|e| e.occurred_at >= start && e.occurred_at <= end)
209 .cloned()
210 .collect()
211 }
212
213 pub async fn clear_history(&self) {
215 self.history.write().await.clear();
216 }
217
218 pub async fn handler_count(&self) -> usize {
220 self.handlers
221 .read()
222 .await
223 .values()
224 .map(|v| v.len())
225 .sum()
226 }
227
228 async fn store_event(&self, envelope: &EventEnvelope<E>) {
233 let mut history = self.history.write().await;
234 history.push(envelope.clone());
235
236 let cutoff = Utc::now() - chrono::Duration::seconds(self.config.retention_seconds as i64);
238 history.retain(|e| e.published_at > cutoff);
239
240 while history.len() > self.config.max_history_size {
242 history.remove(0);
243 }
244 }
245
246 async fn dispatch(&self, envelope: EventEnvelope<E>) -> Result<(), EventError> {
247 let handlers = self.handlers.read().await;
248
249 let mut handlers_to_call = Vec::new();
251
252 if let Some(type_handlers) = handlers.get(envelope.event_type) {
253 handlers_to_call.extend(type_handlers.iter().cloned());
254 }
255
256 if let Some(wildcard_handlers) = handlers.get("*") {
258 handlers_to_call.extend(wildcard_handlers.iter().cloned());
259 }
260
261 for handler in handlers_to_call {
263 if let Err(e) = handler.handle(envelope.clone()).await {
264 tracing::error!(
265 handler = %handler.name(),
266 event_type = %envelope.event_type,
267 error = ?e,
268 "Event handler error"
269 );
270 }
272 }
273
274 Ok(())
275 }
276}
277
278impl<E: DomainEvent> Default for EventBus<E> {
279 fn default() -> Self {
280 Self::new()
281 }
282}
283
284impl<E: DomainEvent> Clone for EventBus<E> {
285 fn clone(&self) -> Self {
286 Self {
287 sender: self.sender.clone(),
288 config: self.config.clone(),
289 handlers: Arc::clone(&self.handlers),
290 history: Arc::clone(&self.history),
291 }
292 }
293}
294
295#[cfg(test)]
296mod tests {
297 use super::*;
298 use crate::handler::CollectingHandler;
299
300 #[derive(Clone, Debug)]
301 struct TestEvent {
302 id: String,
303 message: String,
304 }
305
306 impl DomainEvent for TestEvent {
307 fn event_type(&self) -> &'static str {
308 "TestEvent"
309 }
310
311 fn aggregate_id(&self) -> &str {
312 &self.id
313 }
314 }
315
316 #[tokio::test]
317 async fn test_event_bus_publish() {
318 let bus = EventBus::<TestEvent>::with_config(EventBusConfig::with_persistence());
319
320 let event = TestEvent {
321 id: "test-123".to_string(),
322 message: "Hello".to_string(),
323 };
324
325 bus.publish(event).await.unwrap();
326
327 let history = bus.history().await;
328 assert_eq!(history.len(), 1);
329 assert_eq!(history[0].event_type, "TestEvent");
330 }
331
332 #[tokio::test]
333 async fn test_event_bus_subscribe() {
334 let bus = EventBus::<TestEvent>::new();
335 let mut rx = bus.subscribe();
336
337 let event = TestEvent {
338 id: "test-123".to_string(),
339 message: "Hello".to_string(),
340 };
341
342 bus.publish(event).await.unwrap();
343
344 let envelope = rx.recv().await.unwrap();
345 assert_eq!(envelope.event_type, "TestEvent");
346 assert_eq!(envelope.aggregate_id, "test-123");
347 }
348
349 #[tokio::test]
350 async fn test_event_bus_handler() {
351 let bus = EventBus::<TestEvent>::new();
352 let handler = Arc::new(CollectingHandler::<TestEvent>::new());
353
354 bus.register_handler(handler.clone()).await;
355
356 let event = TestEvent {
357 id: "test-123".to_string(),
358 message: "Hello".to_string(),
359 };
360
361 bus.publish(event).await.unwrap();
362
363 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
365
366 assert_eq!(handler.count().await, 1);
367 }
368
369 #[tokio::test]
370 async fn test_events_for_aggregate() {
371 let bus = EventBus::<TestEvent>::with_config(EventBusConfig::with_persistence());
372
373 bus.publish(TestEvent {
374 id: "agg-1".to_string(),
375 message: "First".to_string(),
376 })
377 .await
378 .unwrap();
379
380 bus.publish(TestEvent {
381 id: "agg-1".to_string(),
382 message: "Second".to_string(),
383 })
384 .await
385 .unwrap();
386
387 bus.publish(TestEvent {
388 id: "agg-2".to_string(),
389 message: "Other".to_string(),
390 })
391 .await
392 .unwrap();
393
394 let events = bus.events_for_aggregate("agg-1").await;
395 assert_eq!(events.len(), 2);
396 }
397}