use crate::AppState;
use axum::extract::State;
use axum::response::sse::{Event as SseEvent, KeepAlive, Sse};
use axum::response::IntoResponse;
use std::convert::Infallible;
use std::time::Duration;
use tokio::sync::broadcast::error::RecvError;
const KEEPALIVE: Duration = Duration::from_secs(15);
pub async fn events_sse(State(state): State<AppState>) -> impl IntoResponse {
let mut events = state.service.subscribe_events();
let stream = async_stream::stream! {
loop {
match events.recv().await {
Ok(event) => {
let Ok(json) = serde_json::to_string(&event) else { continue };
yield Ok::<_, Infallible>(
SseEvent::default().event(event.kind.name()).data(json),
);
}
Err(RecvError::Lagged(skipped)) => {
tracing::debug!(skipped, "event client lagged");
yield Ok(SseEvent::default().event("lagged").data(skipped.to_string()));
}
Err(RecvError::Closed) => break,
}
}
};
Sse::new(stream).keep_alive(KeepAlive::new().interval(KEEPALIVE).text("keep-alive"))
}