use axum::{
extract::State,
response::sse::{Event, KeepAlive, Sse},
Json,
};
use futures::stream::Stream;
use wsb::prelude::*;
use std::convert::Infallible;
use crate::web::machine_web::MachineWeb;
const INTERVAL: std::time::Duration = std::time::Duration::from_secs(2);
pub async fn host_snapshot(State(state): State<MachineWeb>) -> Json<wsb::host::Sample> {
let root = state.volume_root.clone();
let sample = tokio::task::spawn_blocking(move || {
let mut sampler = wsb::host::Sampler::new();
sampler.sample(&root)
})
.await
.unwrap_or_default();
Json(sample)
}
pub async fn host_stream(
State(state): State<MachineWeb>,
) -> Sse<impl Stream<Item = Result<Event, Infallible>>> {
let root = state.volume_root.clone();
let stream = async_stream::stream! {
let mut sampler = wsb::host::Sampler::new();
loop {
let root = root.clone();
let (next, sample) = match tokio::task::spawn_blocking(move || {
let mut moved = sampler;
let sample = moved.sample(&root);
(moved, sample)
})
.await
{
Ok(pair) => pair,
Err(error) => {
tracing::warn!(%error, "the host sampler panicked");
break;
}
};
sampler = next;
match serde_json::to_string(&sample) {
Ok(payload) => yield Ok(Event::default().event("host").data(payload)),
Err(error) => {
tracing::warn!(%error, "a host sample could not be encoded");
break;
}
}
tokio::time::sleep(INTERVAL).await;
}
};
Sse::new(stream).keep_alive(KeepAlive::default())
}