Skip to main content

awa_ui/handlers/
runtime.rs

1use axum::extract::{Query, State};
2use axum::Json;
3use serde::Deserialize;
4
5use awa_model::admin;
6use awa_model::storage;
7
8use crate::cache::CacheError;
9use crate::error::ApiError;
10use crate::state::AppState;
11
12/// Query parameters accepted by `GET /api/storage`.
13///
14/// `history=true` opts in to the epoch-anchored backlog history field on
15/// the response. The 0.6 server has no persistent store for these samples
16/// (see #180), so the field is currently an empty slice — clients
17/// accumulate samples themselves, keyed by `transition_epoch`. The query
18/// param exists so the contract is stable for future versions that may
19/// add a server-side ring buffer without changing the API shape.
20#[derive(Debug, Default, Deserialize)]
21pub struct StorageQuery {
22    #[serde(default)]
23    pub history: bool,
24}
25
26pub async fn get_runtime(
27    State(state): State<AppState>,
28) -> Result<Json<admin::RuntimeOverview>, ApiError> {
29    let pool = state.pool.clone();
30    let overview = state
31        .cache
32        .runtime
33        .try_get_with((), async {
34            admin::runtime_overview(&pool)
35                .await
36                .map_err(CacheError::from)
37        })
38        .await?;
39    Ok(Json(overview))
40}
41
42pub async fn list_queue_runtime(
43    State(state): State<AppState>,
44) -> Result<Json<Vec<admin::QueueRuntimeSummary>>, ApiError> {
45    let pool = state.pool.clone();
46    let summary = state
47        .cache
48        .queue_runtime
49        .try_get_with((), async {
50            admin::queue_runtime_summary(&pool)
51                .await
52                .map_err(CacheError::from)
53        })
54        .await?;
55    Ok(Json(summary))
56}
57
58pub async fn get_storage(
59    State(state): State<AppState>,
60    Query(query): Query<StorageQuery>,
61) -> Result<Json<storage::StorageStatusReport>, ApiError> {
62    let pool = state.pool.clone();
63    let mut report = state
64        .cache
65        .storage
66        .try_get_with((), async {
67            storage::status_report(&pool)
68                .await
69                .map_err(CacheError::from)
70        })
71        .await?;
72    if query.history {
73        // Per #180 (rejected new audit table) the 0.6 server doesn't
74        // accumulate samples. We still return the field — as an empty
75        // vector — so clients can rely on its presence to detect the
76        // contract and start their own client-side accumulation.
77        report.history = Some(Vec::new());
78    }
79    Ok(Json(report))
80}