use crate::models::SessionId;
use tokio::sync::broadcast;
#[derive(Debug, Clone)]
pub enum DataEvent {
StatsUpdated,
SessionCreated(SessionId),
SessionUpdated(SessionId),
ConfigChanged(ConfigScope),
AnalyticsUpdated,
LoadCompleted,
WatcherError(String),
LiveSessionStatusChanged,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ConfigScope {
Global,
Project(String),
Local(String),
Mcp,
}
pub struct EventBus {
sender: broadcast::Sender<DataEvent>,
}
impl EventBus {
pub fn new(capacity: usize) -> Self {
let (sender, _) = broadcast::channel(capacity);
Self { sender }
}
pub fn default_capacity() -> Self {
Self::new(256)
}
pub fn publish(&self, event: DataEvent) {
let _ = self.sender.send(event);
}
pub fn subscribe(&self) -> broadcast::Receiver<DataEvent> {
self.sender.subscribe()
}
pub fn subscriber_count(&self) -> usize {
self.sender.receiver_count()
}
}
impl Default for EventBus {
fn default() -> Self {
Self::default_capacity()
}
}
impl Clone for EventBus {
fn clone(&self) -> Self {
Self {
sender: self.sender.clone(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_event_bus_publish_subscribe() {
let bus = EventBus::default_capacity();
let mut rx = bus.subscribe();
bus.publish(DataEvent::StatsUpdated);
bus.publish(DataEvent::SessionCreated(SessionId::from("test-session")));
let event1 = rx.recv().await.unwrap();
assert!(matches!(event1, DataEvent::StatsUpdated));
let event2 = rx.recv().await.unwrap();
assert!(
matches!(event2, DataEvent::SessionCreated(ref id) if id.as_str() == "test-session")
);
}
#[tokio::test]
async fn test_event_bus_multiple_subscribers() {
let bus = EventBus::default_capacity();
let mut rx1 = bus.subscribe();
let mut rx2 = bus.subscribe();
assert_eq!(bus.subscriber_count(), 2);
bus.publish(DataEvent::LoadCompleted);
let e1 = rx1.recv().await.unwrap();
let e2 = rx2.recv().await.unwrap();
assert!(matches!(e1, DataEvent::LoadCompleted));
assert!(matches!(e2, DataEvent::LoadCompleted));
}
#[test]
fn test_event_bus_no_subscribers_ok() {
let bus = EventBus::default_capacity();
bus.publish(DataEvent::StatsUpdated);
}
}