Files
foxhunt/services/api_gateway/src/health.rs
jgrusewski 7458f1be01 feat(wave12): E2E validation complete - 225-feature pipeline ready
 Validation Results:
- PPO training: 24.2s (1 epoch, 950 samples, dim=225)
- Feature extraction: 105μs/bar (9.5x faster than target)
- Model checkpoint: 293KB (147KB actor + 146KB critic)
- GPU memory: 145MB used (96.4% headroom)
- Zero dimension mismatches

📊 Success Criteria (5/5):
 Feature dimension = 225 (Wave C 201 + Wave D 24)
 Model state_dim = 225
 Training completed without errors
 Checkpoint saved successfully
 No dimension mismatch errors

📁 Training Data Ready:
- ES.FUT: 2.9MB, 180 days
- NQ.FUT: 4.4MB, 180 days
- 6E.FUT: 2.8MB, 180 days
- ZN.FUT: 65KB, 90 days (clean)

🚀 Next: Full production model retraining (4 models, ~10min GPU time)

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 22:48:04 +02:00

134 lines
3.5 KiB
Rust

//! Health check endpoints for API Gateway service
//!
//! Provides HTTP-based health and readiness endpoints for Kubernetes probes.
//! These endpoints don't require authentication to allow load balancers and
//! orchestrators to check service health.
use axum::{extract::State, http::StatusCode, routing::get, Json, Router};
use serde::Serialize;
use std::sync::Arc;
use sqlx::PgPool;
use redis::aio::ConnectionManager;
/// Health status response
#[derive(Serialize)]
pub struct HealthResponse {
/// Service status
pub status: &'static str,
/// Service name
pub service: &'static str,
/// Service version
pub version: &'static str,
}
/// Detailed health status with dependency checks
#[derive(Serialize)]
pub struct DetailedHealthResponse {
/// Service status
pub status: &'static str,
/// Service name
pub service: &'static str,
/// Service version
pub version: &'static str,
/// Database connectivity
pub database: bool,
/// Redis connectivity
pub redis: bool,
}
/// Shared health check state
#[derive(Clone)]
pub struct HealthState {
/// PostgreSQL connection pool
pub db_pool: Option<PgPool>,
/// Redis connection manager
pub redis: Option<ConnectionManager>,
}
/// Creates the health check router with /health and /ready endpoints
pub fn health_router(state: HealthState) -> Router {
Router::new()
.route("/health", get(health_check))
.route("/ready", get(readiness_check))
.with_state(Arc::new(state))
}
/// Liveness probe - indicates service is running
/// Returns 200 OK if the service process is alive
async fn health_check() -> Json<HealthResponse> {
Json(HealthResponse {
status: "healthy",
service: "api_gateway",
version: env!("CARGO_PKG_VERSION"),
})
}
/// Readiness probe - indicates service is ready to accept requests
/// Checks database and Redis connectivity
async fn readiness_check(
State(state): State<Arc<HealthState>>,
) -> Result<Json<DetailedHealthResponse>, StatusCode> {
let mut db_ok = false;
let mut redis_ok = false;
// Check database connectivity
if let Some(ref pool) = state.db_pool {
db_ok = sqlx::query("SELECT 1")
.fetch_one(pool)
.await
.is_ok();
}
// Check Redis connectivity
if let Some(ref mut redis_conn) = state.redis.clone() {
use redis::AsyncCommands;
redis_ok = redis_conn.ping::<()>().await.is_ok();
}
// Service is ready only if all dependencies are healthy
let is_ready = db_ok && redis_ok;
let status = if is_ready { "ready" } else { "not_ready" };
let http_status = if is_ready {
StatusCode::OK
} else {
StatusCode::SERVICE_UNAVAILABLE
};
let response = DetailedHealthResponse {
status,
service: "api_gateway",
version: env!("CARGO_PKG_VERSION"),
database: db_ok,
redis: redis_ok,
};
if is_ready {
Ok(Json(response))
} else {
Err(http_status)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_health_check() {
let response = health_check().await;
assert_eq!(response.status, "healthy");
assert_eq!(response.service, "api_gateway");
}
#[tokio::test]
async fn test_readiness_check_without_deps() {
let state = Arc::new(HealthState {
db_pool: None,
redis: None,
});
let result = readiness_check(State(state)).await;
assert!(result.is_err());
}
}