| |
| |
| |
| |
| |
|
|
| use axum::{ |
| body::Body, |
| extract::{Path, State}, |
| http::{header, StatusCode}, |
| response::Response, |
| }; |
| use std::sync::Arc; |
| use tokio_stream::wrappers::BroadcastStream; |
| use tokio_stream::StreamExt; |
|
|
| use super::routes::AppState; |
|
|
| pub async fn events( |
| State(state): State<Arc<AppState>>, |
| Path(id): Path<String>, |
| ) -> Result<Response<Body>, StatusCode> { |
| let rx = state.solver.subscribe(&id).ok_or(StatusCode::NOT_FOUND)?; |
| let bootstrap_json = state |
| .solver |
| .bootstrap_event(&id) |
| .map_err(|_| StatusCode::NOT_FOUND)?; |
| let bootstrap = tokio_stream::iter(std::iter::once(Ok::<_, std::convert::Infallible>( |
| format!("data: {}\n\n", bootstrap_json).into_bytes(), |
| ))); |
|
|
| let live = BroadcastStream::new(rx).filter_map(|msg| match msg { |
| Ok(json) => Some(Ok::<_, std::convert::Infallible>( |
| format!("data: {}\n\n", json).into_bytes(), |
| )), |
| |
| |
| |
| Err(_) => None, |
| }); |
|
|
| let stream = bootstrap.chain(live); |
|
|
| Ok(Response::builder() |
| .header(header::CONTENT_TYPE, "text/event-stream") |
| .header(header::CACHE_CONTROL, "no-cache") |
| .header("X-Accel-Buffering", "no") |
| .body(Body::from_stream(stream)) |
| .unwrap()) |
| } |
|
|