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