sokuto_server/handlers/
ops.rs1use std::sync::Arc;
7
8use axum::Extension;
9use axum::extract::State;
10use axum::http::StatusCode;
11use axum::response::{IntoResponse, Response};
12use metrics_exporter_prometheus::PrometheusHandle;
13use serde::Serialize;
14use utoipa::ToSchema;
15
16use crate::state::AppState;
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, ToSchema)]
20pub struct HealthStatusResponse {
21 pub status: String,
23}
24
25#[utoipa::path(
29 get,
30 path = "/health",
31 tag = "Operations",
32 responses(
33 (status = 200, description = "プロセス正常稼働中", body = HealthStatusResponse)
34 )
35)]
36pub async fn health_handler() -> impl IntoResponse {
37 axum::Json(HealthStatusResponse {
38 status: "ok".to_string(),
39 })
40}
41
42#[utoipa::path(
46 get,
47 path = "/ready",
48 tag = "Operations",
49 responses(
50 (status = 200, description = "推論準備完了", body = HealthStatusResponse),
51 (status = 503, description = "推論エンジン未準備", body = HealthStatusResponse)
52 )
53)]
54pub async fn ready_handler(State(state): State<Arc<AppState>>) -> Response {
55 if state.is_ready() {
56 (
57 StatusCode::OK,
58 axum::Json(HealthStatusResponse {
59 status: "ready".to_string(),
60 }),
61 )
62 .into_response()
63 } else {
64 (
65 StatusCode::SERVICE_UNAVAILABLE,
66 axum::Json(HealthStatusResponse {
67 status: "not_ready".to_string(),
68 }),
69 )
70 .into_response()
71 }
72}
73
74#[utoipa::path(
78 get,
79 path = "/metrics",
80 tag = "Operations",
81 responses(
82 (status = 200, description = "Prometheus メトリクス出力", content_type = "text/plain; version=0.0.4")
83 )
84)]
85pub async fn metrics_handler(
86 Extension(prometheus_handle): Extension<Option<PrometheusHandle>>,
87) -> impl IntoResponse {
88 match prometheus_handle {
89 Some(handle) => (
90 StatusCode::OK,
91 [("content-type", "text/plain; version=0.0.4; charset=utf-8")],
92 handle.render(),
93 )
94 .into_response(),
95 None => (
96 StatusCode::SERVICE_UNAVAILABLE,
97 "Prometheus メトリクスレコーダーが有効化されていません。",
98 )
99 .into_response(),
100 }
101}