2023-06-03 23:03:58 +00:00
|
|
|
use std::convert::Infallible;
|
2023-06-07 01:14:29 +00:00
|
|
|
use std::str::from_utf8;
|
2023-06-03 23:03:58 +00:00
|
|
|
use std::time::Duration;
|
|
|
|
|
2023-06-07 01:14:29 +00:00
|
|
|
use ansi_to_html::convert_escaped;
|
2023-06-03 23:03:58 +00:00
|
|
|
use axum::extract::State;
|
|
|
|
use axum::response::{
|
|
|
|
sse::{Event, Sse},
|
|
|
|
Response,
|
|
|
|
};
|
|
|
|
use bytes::Bytes;
|
2023-06-07 01:14:29 +00:00
|
|
|
use maud::{html, PreEscaped};
|
2023-06-03 23:03:58 +00:00
|
|
|
use tokio::sync::watch::Receiver;
|
|
|
|
use tokio_stream::wrappers::WatchStream;
|
|
|
|
use tokio_stream::Stream;
|
|
|
|
use tokio_stream::StreamExt;
|
2023-06-03 05:09:25 +00:00
|
|
|
|
|
|
|
use crate::error::Result;
|
|
|
|
use crate::log::MEM_LOG;
|
2023-06-03 23:03:58 +00:00
|
|
|
use crate::partials::layout::Layout;
|
2023-06-03 05:09:25 +00:00
|
|
|
|
|
|
|
pub async fn get(layout: Layout) -> Result<Response> {
|
|
|
|
let mem_buf = MEM_LOG.lock().unwrap();
|
|
|
|
Ok(layout.render(html! {
|
2023-06-03 23:03:58 +00:00
|
|
|
turbo-stream-source src="/log/stream" {}
|
2023-06-07 01:14:29 +00:00
|
|
|
pre id="log" { (PreEscaped(convert_escaped(from_utf8(mem_buf.as_slices().0).unwrap()).unwrap())) }
|
2023-06-03 05:09:25 +00:00
|
|
|
}))
|
|
|
|
}
|
2023-06-03 23:03:58 +00:00
|
|
|
|
|
|
|
pub async fn stream(
|
|
|
|
State(log_receiver): State<Receiver<Bytes>>,
|
|
|
|
) -> Sse<impl Stream<Item = Result<Event, Infallible>>> {
|
|
|
|
let log_stream = WatchStream::new(log_receiver);
|
|
|
|
let log_stream = log_stream.map(|line| {
|
2023-06-07 01:14:29 +00:00
|
|
|
Ok(Event::default().data(
|
|
|
|
html! {
|
|
|
|
turbo-stream action="append" target="log" {
|
|
|
|
template {
|
|
|
|
(PreEscaped(convert_escaped(from_utf8(&line).unwrap()).unwrap()))
|
|
|
|
}
|
2023-06-03 23:03:58 +00:00
|
|
|
}
|
|
|
|
}
|
2023-06-07 01:14:29 +00:00
|
|
|
.into_string(),
|
|
|
|
))
|
2023-06-03 23:03:58 +00:00
|
|
|
});
|
|
|
|
Sse::new(log_stream).keep_alive(
|
|
|
|
axum::response::sse::KeepAlive::new()
|
|
|
|
.interval(Duration::from_secs(15))
|
|
|
|
.text("keep-alive-text"),
|
|
|
|
)
|
|
|
|
}
|