elif_http/
minimal_server.rs1use crate::{HttpConfig, HttpError, HttpResult};
6use elif_core::Container;
7use axum::{
8 Router,
9 routing::get,
10 response::Json,
11};
12use serde_json::{json, Value};
13use std::net::SocketAddr;
14use std::sync::Arc;
15use tokio::signal;
16use tracing::info;
17
18pub struct MinimalHttpServer {
20 addr: SocketAddr,
21}
22
23impl MinimalHttpServer {
24 pub fn new(container: Arc<Container>, config: HttpConfig) -> HttpResult<Self> {
26 let app_config = container.config();
27 let addr = format!("{}:{}", app_config.server.host, app_config.server.port)
28 .parse::<SocketAddr>()
29 .map_err(|e| HttpError::config(format!("Invalid server address: {}", e)))?;
30
31 Ok(Self { addr })
32 }
33
34 pub async fn run(self) -> HttpResult<()> {
36 info!("Starting minimal HTTP server on {}", self.addr);
37
38 let router = Router::new()
40 .route("/health", get(minimal_health_check));
41
42 let listener = tokio::net::TcpListener::bind(self.addr)
43 .await
44 .map_err(|e| HttpError::startup(format!("Failed to bind to {}: {}", self.addr, e)))?;
45
46 info!("Minimal HTTP server listening on {}", self.addr);
47
48 axum::serve(listener, router)
49 .with_graceful_shutdown(minimal_shutdown_signal())
50 .await
51 .map_err(|e| HttpError::startup(format!("Server failed: {}", e)))?;
52
53 info!("Minimal HTTP server stopped gracefully");
54 Ok(())
55 }
56}
57
58pub async fn minimal_health_check() -> Json<Value> {
60 Json(json!({
61 "status": "healthy",
62 "timestamp": chrono::Utc::now().to_rfc3339(),
63 "version": "0.1.0",
64 "server": "minimal"
65 }))
66}
67
68async fn minimal_shutdown_signal() {
70 let ctrl_c = async {
71 signal::ctrl_c()
72 .await
73 .expect("failed to install Ctrl+C handler");
74 };
75
76 #[cfg(unix)]
77 let terminate = async {
78 signal::unix::signal(signal::unix::SignalKind::terminate())
79 .expect("failed to install signal handler")
80 .recv()
81 .await;
82 };
83
84 #[cfg(not(unix))]
85 let terminate = std::future::pending::<()>();
86
87 tokio::select! {
88 _ = ctrl_c => {
89 info!("Received Ctrl+C, initiating graceful shutdown");
90 },
91 _ = terminate => {
92 info!("Received terminate signal, initiating graceful shutdown");
93 },
94 }
95}