use std::sync::Arc;
use std::time::Duration;
use axum::routing::{get, post};
use axum::Router;
use metrics_exporter_prometheus::PrometheusHandle;
use sqlx_postgres::PgPool;
use tower::ServiceBuilder;
use tower_http::request_id::{MakeRequestUuid, PropagateRequestIdLayer, SetRequestIdLayer};
use tower_http::timeout::TimeoutLayer;
use tower_http::trace::TraceLayer;
use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi;
use crate::api::openapi::ApiDoc;
use crate::api::routes;
#[derive(Clone)]
pub struct AppState {
pub pool: PgPool,
pub metrics: Arc<PrometheusHandle>,
}
pub fn build_router(state: AppState) -> Router {
let swagger = SwaggerUi::new("/docs").url("/api-docs/openapi.json", ApiDoc::openapi());
let middleware = ServiceBuilder::new()
.layer(SetRequestIdLayer::x_request_id(MakeRequestUuid))
.layer(
TraceLayer::new_for_http().make_span_with(|req: &axum::http::Request<_>| {
let request_id = req
.headers()
.get("x-request-id")
.and_then(|v| v.to_str().ok())
.unwrap_or("");
tracing::info_span!(
"http",
method = %req.method(),
uri = %req.uri(),
request_id = %request_id,
)
}),
)
.layer(PropagateRequestIdLayer::x_request_id())
.layer(TimeoutLayer::with_status_code(
axum::http::StatusCode::GATEWAY_TIMEOUT,
Duration::from_secs(30),
));
Router::new()
.route(
"/jobs",
post(routes::jobs::create_job).get(routes::jobs::list_jobs),
)
.route("/jobs/{id}", get(routes::jobs::get_job))
.route("/jobs/{id}/cancel", post(routes::jobs::cancel_job))
.route("/health", get(routes::health::health))
.route("/metrics", get(routes::metrics::metrics))
.merge(swagger)
.layer(middleware)
.with_state(state)
}