use tokio::sync::broadcast;
use super::protocol::WebEvent;
pub struct WebBroadcaster {
tx: broadcast::Sender<WebEvent>,
}
impl WebBroadcaster {
pub fn new(capacity: usize) -> Self {
let (tx, _rx) = broadcast::channel(capacity);
Self { tx }
}
#[must_use]
pub fn send(&self, event: WebEvent) -> usize {
self.tx.send(event).unwrap_or(0)
}
pub fn subscribe(&self) -> broadcast::Receiver<WebEvent> {
self.tx.subscribe()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn broadcast_to_multiple_receivers() {
let bc = WebBroadcaster::new(16);
let mut rx1 = bc.subscribe();
let mut rx2 = bc.subscribe();
let event = WebEvent::BufferClosed {
buffer_id: "test/chan".into(),
};
let count = bc.send(event);
assert_eq!(count, 2);
let ev1 = rx1.recv().await.unwrap();
let ev2 = rx2.recv().await.unwrap();
assert!(matches!(ev1, WebEvent::BufferClosed { .. }));
assert!(matches!(ev2, WebEvent::BufferClosed { .. }));
}
#[test]
fn broadcast_no_receivers_does_not_panic() {
let bc = WebBroadcaster::new(16);
let count = bc.send(WebEvent::BufferClosed {
buffer_id: "x".into(),
});
assert_eq!(count, 0);
}
#[tokio::test]
async fn dropped_receiver_does_not_block() {
let bc = WebBroadcaster::new(16);
let rx = bc.subscribe();
drop(rx);
let count = bc.send(WebEvent::BufferClosed {
buffer_id: "y".into(),
});
assert_eq!(count, 0);
}
}