backbone_messaging/
envelope.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7use crate::DomainEvent;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct EventEnvelope<E: DomainEvent> {
15 pub id: String,
17 pub event_type: &'static str,
19 pub aggregate_id: String,
21 pub aggregate_type: &'static str,
23 #[serde(skip)]
25 event: Option<E>,
26 pub occurred_at: DateTime<Utc>,
28 pub published_at: DateTime<Utc>,
30 pub correlation_id: Option<String>,
32 pub causation_id: Option<String>,
34 pub version: u32,
36 #[serde(default)]
38 pub metadata: std::collections::HashMap<String, String>,
39}
40
41impl<E: DomainEvent> EventEnvelope<E> {
42 pub fn new(event: E) -> Self {
44 Self {
45 id: Uuid::new_v4().to_string(),
46 event_type: event.event_type(),
47 aggregate_id: event.aggregate_id().to_string(),
48 aggregate_type: event.aggregate_type(),
49 occurred_at: event.occurred_at(),
50 published_at: Utc::now(),
51 version: event.version(),
52 event: Some(event),
53 correlation_id: None,
54 causation_id: None,
55 metadata: std::collections::HashMap::new(),
56 }
57 }
58
59 pub fn event(&self) -> Option<&E> {
61 self.event.as_ref()
62 }
63
64 pub fn into_event(self) -> Option<E> {
66 self.event
67 }
68
69 pub fn with_correlation_id(mut self, id: impl Into<String>) -> Self {
71 self.correlation_id = Some(id.into());
72 self
73 }
74
75 pub fn with_causation_id(mut self, id: impl Into<String>) -> Self {
77 self.causation_id = Some(id.into());
78 self
79 }
80
81 pub fn with_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
83 self.metadata.insert(key.into(), value.into());
84 self
85 }
86
87 pub fn is_correlated_with(&self, other: &Self) -> bool {
89 match (&self.correlation_id, &other.correlation_id) {
90 (Some(a), Some(b)) => a == b,
91 _ => false,
92 }
93 }
94
95 pub fn was_caused_by(&self, other: &Self) -> bool {
97 match &self.causation_id {
98 Some(causation) => causation == &other.id,
99 None => false,
100 }
101 }
102}
103
104pub struct EventEnvelopeBuilder<E: DomainEvent> {
106 envelope: EventEnvelope<E>,
107}
108
109impl<E: DomainEvent> EventEnvelopeBuilder<E> {
110 pub fn new(event: E) -> Self {
112 Self {
113 envelope: EventEnvelope::new(event),
114 }
115 }
116
117 pub fn correlation_id(mut self, id: impl Into<String>) -> Self {
119 self.envelope.correlation_id = Some(id.into());
120 self
121 }
122
123 pub fn causation_id(mut self, id: impl Into<String>) -> Self {
125 self.envelope.causation_id = Some(id.into());
126 self
127 }
128
129 pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
131 self.envelope.metadata.insert(key.into(), value.into());
132 self
133 }
134
135 pub fn build(self) -> EventEnvelope<E> {
137 self.envelope
138 }
139}