use axum::{extract::State, response::Json};
use fusillade::Storage;
use sqlx_pool_router::PoolProvider;
use std::collections::HashMap;
use crate::api::handlers::sla_capacity::parse_window_to_seconds;
use crate::{
AppState,
auth::permissions::{RequiresPermission, operation, resource},
errors::Error,
};
type PendingCountsByModelAndWindow = HashMap<String, HashMap<String, i64>>;
#[utoipa::path(
get,
path = "/admin/api/v1/monitoring/pending-request-counts",
responses(
(status = 200, description = "Pending request counts by model and completion window", body = HashMap<String, HashMap<String, i64>>),
(status = 500, description = "Internal server error"),
),
tag = "monitoring",
)]
#[tracing::instrument(skip_all)]
pub async fn get_pending_request_counts<P: PoolProvider>(
State(state): State<AppState<P>>,
_: RequiresPermission<resource::System, operation::ReadAll>,
) -> Result<Json<PendingCountsByModelAndWindow>, Error> {
let config = state.current_config();
let windows = config
.batches
.allowed_completion_windows
.iter()
.map(|window| (window.clone(), parse_window_to_seconds(window)))
.collect::<Vec<_>>();
let states = vec!["pending".to_string(), "claimed".to_string(), "processing".to_string()]; let model_filter: Vec<String> = Vec::new();
let counts = state
.request_manager
.get_pending_request_counts_by_model_and_completion_window(&windows, &states, &model_filter, false)
.await
.map_err(|e| Error::Internal {
operation: format!("get pending request counts: {}", e),
})?;
Ok(Json(counts))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::api::models::users::Role;
use crate::test::utils::*;
use axum_test::TestServer;
use sqlx::PgPool;
#[sqlx::test]
async fn test_pending_request_counts_requires_system_permission(pool: sqlx::PgPool) {
let (server, _bg): (TestServer, _) = create_test_app(pool.clone(), false).await;
let standard_user = create_test_user(&pool, Role::StandardUser).await;
let response = server
.get("/admin/api/v1/monitoring/pending-request-counts")
.add_header(&add_auth_headers(&standard_user)[0].0, &add_auth_headers(&standard_user)[0].1)
.add_header(&add_auth_headers(&standard_user)[1].0, &add_auth_headers(&standard_user)[1].1)
.await;
response.assert_status(axum::http::StatusCode::FORBIDDEN);
let platform_manager = create_test_user(&pool, Role::PlatformManager).await;
let response = server
.get("/admin/api/v1/monitoring/pending-request-counts")
.add_header(&add_auth_headers(&platform_manager)[0].0, &add_auth_headers(&platform_manager)[0].1)
.add_header(&add_auth_headers(&platform_manager)[1].0, &add_auth_headers(&platform_manager)[1].1)
.await;
response.assert_status_ok();
}
#[sqlx::test]
async fn test_pending_request_counts_returns_empty_when_no_requests(pool: PgPool) {
let (server, _bg): (TestServer, _) = create_test_app(pool.clone(), false).await;
let admin = create_test_admin_user(&pool, Role::PlatformManager).await;
let response = server
.get("/admin/api/v1/monitoring/pending-request-counts")
.add_header(&add_auth_headers(&admin)[0].0, &add_auth_headers(&admin)[0].1)
.add_header(&add_auth_headers(&admin)[1].0, &add_auth_headers(&admin)[1].1)
.await;
response.assert_status_ok();
let counts: HashMap<String, HashMap<String, i64>> = response.json();
assert_eq!(counts.len(), 0, "Should have no pending requests");
}
}