Skip to main content

mlua_swarm_server/
enhance_log.rs

1//! HTTP surface for the `/v1/enhance/log` axis.
2//!
3//! - `GET /v1/enhance/log?blueprint_id=<id>` → list of `LogEntry`s tied to
4//!   that BP, sorted by `ts` ascending. If `blueprint_id` is omitted, returns
5//!   all entries.
6//! - `GET /v1/enhance/log/:issue_id` → a single `LogEntry`. NotFound → 404.
7//!
8//! Shares an `EnhanceLogStore` trait object (= pass in the same instance as
9//! `EnhanceApplication` via `Arc`).
10
11use axum::{
12    extract::{Path, Query, State},
13    http::StatusCode,
14    response::IntoResponse,
15    routing::get,
16    Json, Router,
17};
18use mlua_swarm::blueprint::store::BlueprintId;
19use mlua_swarm::store::enhance_log::{EnhanceLogEntry, EnhanceLogStore, EnhanceLogStoreError};
20use mlua_swarm::store::issue::IssueId;
21use serde::Deserialize;
22use std::sync::Arc;
23
24/// Query params for `GET /v1/enhance/log`.
25#[derive(Debug, Deserialize)]
26pub struct ListQuery {
27    /// When set, restricts the listing to entries tied to this Blueprint id.
28    /// `None` returns all entries.
29    pub blueprint_id: Option<String>,
30}
31
32/// Builds the `/v1/enhance/log*` router backed by the given `EnhanceLogStore`.
33pub fn build_enhance_log_router(store: Arc<dyn EnhanceLogStore>) -> Router {
34    Router::new()
35        .route("/v1/enhance/log", get(list_entries))
36        .route("/v1/enhance/log/:issue_id", get(get_entry))
37        .with_state(store)
38}
39
40async fn list_entries(
41    State(store): State<Arc<dyn EnhanceLogStore>>,
42    Query(q): Query<ListQuery>,
43) -> Result<Json<Vec<EnhanceLogEntry>>, (StatusCode, String)> {
44    let entries = match q.blueprint_id {
45        Some(bp) => store
46            .list_by_blueprint(&BlueprintId::new(bp))
47            .await
48            .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?,
49        None => store
50            .list_all()
51            .await
52            .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?,
53    };
54    Ok(Json(entries))
55}
56
57async fn get_entry(
58    State(store): State<Arc<dyn EnhanceLogStore>>,
59    Path(issue_id): Path<String>,
60) -> impl IntoResponse {
61    match store.get(&IssueId::new(issue_id)).await {
62        Ok(e) => (StatusCode::OK, Json(e)).into_response(),
63        Err(EnhanceLogStoreError::NotFound(_)) => (
64            StatusCode::NOT_FOUND,
65            "enhance log entry not found".to_string(),
66        )
67            .into_response(),
68        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
69    }
70}