1use crate::models::SessionId;
6use tokio::sync::broadcast;
7
8#[derive(Debug, Clone)]
10pub enum DataEvent {
11 StatsUpdated,
13 SessionCreated(SessionId),
15 SessionUpdated(SessionId),
17 ConfigChanged(ConfigScope),
19 AnalyticsUpdated,
21 LoadCompleted,
23 WatcherError(String),
25 LiveSessionStatusChanged,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
31pub enum ConfigScope {
32 Global,
33 Project(String),
34 Local(String),
35 Mcp,
36}
37
38pub struct EventBus {
43 sender: broadcast::Sender<DataEvent>,
44}
45
46impl EventBus {
47 pub fn new(capacity: usize) -> Self {
49 let (sender, _) = broadcast::channel(capacity);
50 Self { sender }
51 }
52
53 pub fn default_capacity() -> Self {
55 Self::new(256)
56 }
57
58 pub fn publish(&self, event: DataEvent) {
60 let _ = self.sender.send(event);
62 }
63
64 pub fn subscribe(&self) -> broadcast::Receiver<DataEvent> {
66 self.sender.subscribe()
67 }
68
69 pub fn subscriber_count(&self) -> usize {
71 self.sender.receiver_count()
72 }
73}
74
75impl Default for EventBus {
76 fn default() -> Self {
77 Self::default_capacity()
78 }
79}
80
81impl Clone for EventBus {
82 fn clone(&self) -> Self {
83 Self {
84 sender: self.sender.clone(),
85 }
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[tokio::test]
94 async fn test_event_bus_publish_subscribe() {
95 let bus = EventBus::default_capacity();
96 let mut rx = bus.subscribe();
97
98 bus.publish(DataEvent::StatsUpdated);
99 bus.publish(DataEvent::SessionCreated(SessionId::from("test-session")));
100
101 let event1 = rx.recv().await.unwrap();
102 assert!(matches!(event1, DataEvent::StatsUpdated));
103
104 let event2 = rx.recv().await.unwrap();
105 assert!(
106 matches!(event2, DataEvent::SessionCreated(ref id) if id.as_str() == "test-session")
107 );
108 }
109
110 #[tokio::test]
111 async fn test_event_bus_multiple_subscribers() {
112 let bus = EventBus::default_capacity();
113 let mut rx1 = bus.subscribe();
114 let mut rx2 = bus.subscribe();
115
116 assert_eq!(bus.subscriber_count(), 2);
117
118 bus.publish(DataEvent::LoadCompleted);
119
120 let e1 = rx1.recv().await.unwrap();
121 let e2 = rx2.recv().await.unwrap();
122
123 assert!(matches!(e1, DataEvent::LoadCompleted));
124 assert!(matches!(e2, DataEvent::LoadCompleted));
125 }
126
127 #[test]
128 fn test_event_bus_no_subscribers_ok() {
129 let bus = EventBus::default_capacity();
130 bus.publish(DataEvent::StatsUpdated);
132 }
133}