1use std::time::SystemTime;
4
5use tokio::sync::broadcast;
6
7#[derive(Debug, Clone)]
9pub struct EventSource {
10 sender: broadcast::Sender<BrokerEvent>,
11}
12
13#[derive(Debug, Clone)]
15pub struct BrokerEvent {
16 pub at: SystemTime,
18 pub kind: BrokerEventKind,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum BrokerEventKind {
25 KeyRotated {
27 key_id: String,
29 new_version: u32,
31 },
32 BundleChanged {
34 trust_domain: String,
36 },
37 Revoked {
39 trust_domain: String,
41 id: String,
43 },
44}
45
46impl Default for EventSource {
47 fn default() -> Self {
48 Self::new()
49 }
50}
51
52impl EventSource {
53 #[must_use]
55 pub fn new() -> Self {
56 let (sender, _) = broadcast::channel(1024);
57 Self { sender }
58 }
59
60 #[must_use]
62 pub fn subscribe(&self) -> broadcast::Receiver<BrokerEvent> {
63 self.sender.subscribe()
64 }
65
66 pub fn key_rotated(&self, key_id: impl Into<String>, new_version: u32) {
68 self.publish(BrokerEventKind::KeyRotated {
69 key_id: key_id.into(),
70 new_version,
71 });
72 }
73
74 pub fn bundle_changed(&self, trust_domain: impl Into<String>) {
76 self.publish(BrokerEventKind::BundleChanged {
77 trust_domain: trust_domain.into(),
78 });
79 }
80
81 pub fn revoked(&self, trust_domain: impl Into<String>, id: impl Into<String>) {
83 self.publish(BrokerEventKind::Revoked {
84 trust_domain: trust_domain.into(),
85 id: id.into(),
86 });
87 }
88
89 fn publish(&self, kind: BrokerEventKind) {
90 let _receivers = self.sender.send(BrokerEvent {
91 at: SystemTime::now(),
92 kind,
93 });
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[tokio::test]
102 async fn subscribers_receive_events() {
103 let source = EventSource::new();
104 let mut rx = source.subscribe();
105 source.key_rotated("app.key", 2);
106 let event = rx.recv().await.expect("event received");
107 assert_eq!(
108 event.kind,
109 BrokerEventKind::KeyRotated {
110 key_id: "app.key".to_string(),
111 new_version: 2,
112 }
113 );
114 }
115}