use crate::event::TelemetryEvent;
use tokio::sync::broadcast;
pub const BUS_CAPACITY: usize = 4_096;
#[derive(Debug, Clone)]
pub struct EventBus {
sender: broadcast::Sender<TelemetryEvent>,
}
impl EventBus {
pub fn new() -> Self {
Self::with_capacity(BUS_CAPACITY)
}
pub fn with_capacity(capacity: usize) -> Self {
let (sender, _) = broadcast::channel(capacity);
Self { sender }
}
pub fn subscribe(&self) -> broadcast::Receiver<TelemetryEvent> {
self.sender.subscribe()
}
pub fn publish(&self, event: TelemetryEvent) -> Result<usize, TelemetryEvent> {
self.sender.send(event).map_err(|e| e.0)
}
}
impl Default for EventBus {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn ev() -> TelemetryEvent {
TelemetryEvent {
topic: "t".into(),
id: "i".into(),
class: "c".into(),
ts: 1,
payload: serde_json::Value::Null,
ingress_ts: 2,
}
}
#[tokio::test]
async fn subscriber_receives_published_event() {
let bus = EventBus::new();
let mut rx = bus.subscribe();
bus.publish(ev()).unwrap();
let got = rx.recv().await.unwrap();
assert_eq!(got.ingress_ts, 2);
}
#[tokio::test]
async fn multiple_subscribers_each_receive() {
let bus = EventBus::new();
let mut a = bus.subscribe();
let mut b = bus.subscribe();
bus.publish(ev()).unwrap();
assert_eq!(a.recv().await.unwrap().topic, "t");
assert_eq!(b.recv().await.unwrap().topic, "t");
}
#[tokio::test]
async fn lagged_subscriber_gets_lagged_error_then_new_events() {
let bus = EventBus::with_capacity(2);
let mut rx = bus.subscribe();
bus.publish(ev()).unwrap();
bus.publish(ev()).unwrap();
bus.publish(ev()).unwrap();
assert!(matches!(
rx.recv().await,
Err(broadcast::error::RecvError::Lagged(_))
));
assert!(rx.recv().await.is_ok());
}
}