use tokio::sync::broadcast;
use super::event::QueryEvent;
const BROADCAST_CAPACITY: usize = 1000;
pub struct LiveLog {
tx: broadcast::Sender<QueryEvent>,
}
impl LiveLog {
pub fn new() -> Self {
let (tx, _) = broadcast::channel(BROADCAST_CAPACITY);
Self { tx }
}
pub fn publish(&self, event: QueryEvent) {
let _ = self.tx.send(event);
}
pub fn subscribe(&self) -> broadcast::Receiver<QueryEvent> {
self.tx.subscribe()
}
}
impl Default for LiveLog {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
codec::{message::Qtype, name::Name},
resolver::pipeline::Outcome,
telemetry::event::QueryEvent,
};
use std::net::SocketAddr;
fn make_event(label: &str, outcome: Outcome) -> QueryEvent {
let client: SocketAddr = "203.0.113.5:1234".parse().unwrap();
let qname: Name = format!("{label}.example.com").parse().unwrap();
QueryEvent::new(client, qname, Qtype::A, outcome)
}
#[tokio::test]
async fn publish_delivers_to_subscriber() {
let log = LiveLog::new();
let mut rx = log.subscribe();
let event = make_event("a", Outcome::Forwarded);
log.publish(event.clone());
let received = tokio::time::timeout(std::time::Duration::from_secs(1), rx.recv())
.await
.expect("timeout waiting for broadcast")
.expect("broadcast channel closed");
assert_eq!(received.qname.to_string(), event.qname.to_string());
}
#[tokio::test]
async fn late_subscriber_only_sees_post_subscribe_events() {
let log = LiveLog::new();
log.publish(make_event("pre0", Outcome::Cached));
let mut rx = log.subscribe();
let post_event = make_event("post0", Outcome::Forwarded);
log.publish(post_event.clone());
let received = tokio::time::timeout(std::time::Duration::from_secs(1), rx.recv())
.await
.expect("timeout waiting for broadcast")
.expect("broadcast channel closed");
assert_eq!(
received.qname.to_string(),
post_event.qname.to_string(),
"subscriber should only get the post-subscribe event"
);
let nothing = tokio::time::timeout(std::time::Duration::from_millis(50), rx.recv()).await;
assert!(
nothing.is_err(),
"broadcast channel should be empty after the one post-subscribe event"
);
}
}