backbone_messaging/event.rs
1//! Domain Event trait definition
2
3use chrono::{DateTime, Utc};
4
5/// Trait for domain events
6///
7/// All domain events must implement this trait to be used with the EventBus.
8/// Domain events represent something that happened in the domain that domain
9/// experts care about.
10///
11/// # Example
12///
13/// ```rust,ignore
14/// use backbone_messaging::DomainEvent;
15/// use chrono::{DateTime, Utc};
16///
17/// #[derive(Clone, Debug)]
18/// struct OrderPlaced {
19/// order_id: String,
20/// customer_id: String,
21/// total: f64,
22/// placed_at: DateTime<Utc>,
23/// }
24///
25/// impl DomainEvent for OrderPlaced {
26/// fn event_type(&self) -> &'static str {
27/// "OrderPlaced"
28/// }
29///
30/// fn aggregate_id(&self) -> &str {
31/// &self.order_id
32/// }
33///
34/// fn occurred_at(&self) -> DateTime<Utc> {
35/// self.placed_at
36/// }
37/// }
38/// ```
39pub trait DomainEvent: Clone + Send + Sync + 'static {
40 /// Returns the event type name (e.g., "UserCreated", "OrderPlaced")
41 fn event_type(&self) -> &'static str;
42
43 /// Returns the aggregate ID this event belongs to
44 fn aggregate_id(&self) -> &str;
45
46 /// Returns when the event occurred
47 /// Default implementation returns current time
48 fn occurred_at(&self) -> DateTime<Utc> {
49 Utc::now()
50 }
51
52 /// Returns the aggregate type name (e.g., "User", "Order")
53 /// Default implementation extracts from event type
54 fn aggregate_type(&self) -> &'static str {
55 // Extract aggregate type from event type (e.g., "UserCreated" -> "User")
56 let event_type = self.event_type();
57 // Simple heuristic: find common suffixes
58 for suffix in ["Created", "Updated", "Deleted", "Changed", "Added", "Removed"] {
59 if event_type.ends_with(suffix) {
60 // Return the part before the suffix
61 // This is a compile-time approximation
62 return event_type;
63 }
64 }
65 event_type
66 }
67
68 /// Returns the event version for schema evolution
69 fn version(&self) -> u32 {
70 1
71 }
72}
73
74/// Marker trait for events that can be serialized
75#[allow(dead_code)]
76pub trait SerializableEvent: DomainEvent + serde::Serialize + serde::de::DeserializeOwned {}
77
78impl<T> SerializableEvent for T where T: DomainEvent + serde::Serialize + serde::de::DeserializeOwned {}