Skip to main content

backbone_messaging/
bus.rs

1//! Event Bus implementation
2
3use std::collections::HashMap;
4use std::sync::Arc;
5use tokio::sync::{broadcast, RwLock};
6use chrono::{DateTime, Utc};
7
8use crate::{DomainEvent, EventEnvelope, EventError, EventHandler};
9
10/// Type alias for handler map
11type HandlerMap<E> = Arc<RwLock<HashMap<String, Vec<Arc<dyn EventHandler<E>>>>>>;
12
13/// Configuration for the event bus
14#[derive(Debug, Clone)]
15pub struct EventBusConfig {
16    /// Maximum number of events to buffer in the broadcast channel
17    pub buffer_size: usize,
18    /// Enable event persistence for replay
19    pub persist_events: bool,
20    /// Event retention period in seconds (for persistence)
21    pub retention_seconds: u64,
22    /// Maximum events to keep in history
23    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, // 24 hours
32            max_history_size: 10000,
33        }
34    }
35}
36
37impl EventBusConfig {
38    /// Create config with persistence enabled
39    pub fn with_persistence() -> Self {
40        Self {
41            persist_events: true,
42            ..Default::default()
43        }
44    }
45
46    /// Set buffer size
47    pub fn buffer_size(mut self, size: usize) -> Self {
48        self.buffer_size = size;
49        self
50    }
51
52    /// Set retention period
53    pub fn retention_seconds(mut self, seconds: u64) -> Self {
54        self.retention_seconds = seconds;
55        self
56    }
57}
58
59/// Generic event bus for publishing and subscribing to domain events
60///
61/// The EventBus provides:
62/// - Type-safe publish/subscribe
63/// - Event envelope with metadata
64/// - Handler registration by event type
65/// - Optional event history for replay
66///
67/// # Type Parameters
68///
69/// - `E`: The domain event type (must implement `DomainEvent`)
70///
71/// # Example
72///
73/// ```rust,ignore
74/// use backbone_messaging::{EventBus, EventBusConfig, DomainEvent};
75///
76/// #[derive(Clone, Debug)]
77/// struct UserCreated { user_id: String }
78///
79/// impl DomainEvent for UserCreated {
80///     fn event_type(&self) -> &'static str { "UserCreated" }
81///     fn aggregate_id(&self) -> &str { &self.user_id }
82/// }
83///
84/// let bus = EventBus::<UserCreated>::new();
85/// bus.publish(UserCreated { user_id: "123".into() }).await?;
86/// ```
87pub struct EventBus<E: DomainEvent> {
88    /// Broadcast channel sender
89    sender: broadcast::Sender<EventEnvelope<E>>,
90    /// Configuration
91    config: EventBusConfig,
92    /// Registered handlers by event type
93    handlers: HandlerMap<E>,
94    /// Event history (if persistence enabled)
95    history: Arc<RwLock<Vec<EventEnvelope<E>>>>,
96}
97
98impl<E: DomainEvent> EventBus<E> {
99    /// Create a new event bus with default configuration
100    pub fn new() -> Self {
101        Self::with_config(EventBusConfig::default())
102    }
103
104    /// Create a new event bus with custom configuration
105    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    /// Publish a domain event
116    pub async fn publish(&self, event: E) -> Result<(), EventError> {
117        let envelope = EventEnvelope::new(event);
118        self.publish_envelope(envelope).await
119    }
120
121    /// Publish multiple domain events
122    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    /// Publish an event envelope (with metadata)
130    pub async fn publish_envelope(&self, envelope: EventEnvelope<E>) -> Result<(), EventError> {
131        // Store in history if persistence enabled
132        if self.config.persist_events {
133            self.store_event(&envelope).await;
134        }
135
136        // Broadcast to all subscribers
137        let _ = self.sender.send(envelope.clone());
138
139        // Dispatch to registered handlers
140        self.dispatch(envelope).await?;
141
142        Ok(())
143    }
144
145    /// Register an event handler
146    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            // Handler wants all events - register under wildcard
152            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    /// Subscribe to all events (returns a broadcast receiver)
167    pub fn subscribe(&self) -> broadcast::Receiver<EventEnvelope<E>> {
168        self.sender.subscribe()
169    }
170
171    /// Get event history (if persistence enabled)
172    pub async fn history(&self) -> Vec<EventEnvelope<E>> {
173        self.history.read().await.clone()
174    }
175
176    /// Get events for a specific aggregate
177    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    /// Get events by type
188    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    /// Get events in a time range
199    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    /// Clear event history
214    pub async fn clear_history(&self) {
215        self.history.write().await.clear();
216    }
217
218    /// Get handler count
219    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    // ========================================
229    // Private Methods
230    // ========================================
231
232    async fn store_event(&self, envelope: &EventEnvelope<E>) {
233        let mut history = self.history.write().await;
234        history.push(envelope.clone());
235
236        // Trim old events by retention period
237        let cutoff = Utc::now() - chrono::Duration::seconds(self.config.retention_seconds as i64);
238        history.retain(|e| e.published_at > cutoff);
239
240        // Also trim by max size
241        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        // Get handlers for this specific event type
250        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        // Get wildcard handlers (registered for all events)
257        if let Some(wildcard_handlers) = handlers.get("*") {
258            handlers_to_call.extend(wildcard_handlers.iter().cloned());
259        }
260
261        // Call all handlers
262        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                // Continue dispatching to other handlers
271            }
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        // Give handler time to process
364        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}