2025-11-02 23:37:11 +01:00
|
|
|
use axum::{extract::Path, http::StatusCode, response::{IntoResponse, Response}, routing::get, Router};
|
|
|
|
|
use std::net::SocketAddr;
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
use tracing::{info, warn};
|
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
|
|
use crate::persist::Persist;
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct HttpState {
|
|
|
|
|
persist: Arc<Persist>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn build_router(persist: Arc<Persist>) -> Router {
|
|
|
|
|
let state = HttpState { persist };
|
|
|
|
|
Router::new()
|
2025-11-03 22:36:31 +01:00
|
|
|
.route("/jobs/{request_id}/logs", get(get_logs))
|
2025-11-02 23:37:11 +01:00
|
|
|
.with_state(state)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn get_logs(
|
|
|
|
|
Path(request_id): Path<String>,
|
|
|
|
|
axum::extract::State(state): axum::extract::State<HttpState>,
|
|
|
|
|
) -> Response {
|
|
|
|
|
let Ok(id) = Uuid::parse_str(&request_id) else {
|
|
|
|
|
return StatusCode::BAD_REQUEST.into_response();
|
|
|
|
|
};
|
|
|
|
|
if !state.persist.is_enabled() {
|
|
|
|
|
return (StatusCode::SERVICE_UNAVAILABLE, "persistence disabled").into_response();
|
|
|
|
|
}
|
|
|
|
|
match state.persist.get_logs_text(id).await {
|
|
|
|
|
Ok(Some(text)) => (
|
|
|
|
|
StatusCode::OK,
|
|
|
|
|
[(axum::http::header::CONTENT_TYPE, "text/plain; charset=utf-8")],
|
|
|
|
|
text,
|
|
|
|
|
)
|
|
|
|
|
.into_response(),
|
|
|
|
|
Ok(None) => StatusCode::NOT_FOUND.into_response(),
|
|
|
|
|
Err(e) => {
|
|
|
|
|
warn!(error = %e, request_id = %id, "failed to read logs");
|
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR.into_response()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn serve(addr: SocketAddr, persist: Arc<Persist>, shutdown: impl std::future::Future<Output = ()>) {
|
|
|
|
|
let app = build_router(persist);
|
|
|
|
|
info!(%addr, "http server starting");
|
|
|
|
|
let listener = tokio::net::TcpListener::bind(addr).await.expect("bind http");
|
|
|
|
|
let server = axum::serve(listener, app);
|
|
|
|
|
let _ = tokio::select! {
|
|
|
|
|
_ = server => {},
|
|
|
|
|
_ = shutdown => {},
|
|
|
|
|
};
|
|
|
|
|
}
|