use std::net::SocketAddr;
use std::sync::Arc;
use axum::{Json, Router, extract::State, routing::get};
use eyre::{Context, Result};
use tokio_util::sync::CancellationToken;
use crate::control::manifest::ServerManifest;
pub struct ControlServerConfig {
pub bind_addr: SocketAddr,
pub manifest: Arc<ServerManifest>,
}
pub async fn run_control_server(
config: ControlServerConfig,
cancel: CancellationToken,
) -> Result<()> {
let manifest = config.manifest;
let app = Router::new()
.route("/", get(manifest_handler))
.route("/manifest", get(manifest_handler))
.route("/health", get(health_handler))
.with_state(manifest);
tracing::info!("Control endpoint listening on {}", config.bind_addr);
let listener = tokio::net::TcpListener::bind(config.bind_addr)
.await
.wrap_err_with(|| format!("Failed to bind control endpoint on {}", config.bind_addr))?;
axum::serve(listener, app)
.with_graceful_shutdown(async move {
cancel.cancelled().await;
tracing::info!("Control endpoint received shutdown signal, draining...");
})
.await
.wrap_err("Control endpoint server error")?;
Ok(())
}
async fn manifest_handler(State(manifest): State<Arc<ServerManifest>>) -> Json<ServerManifest> {
Json((*manifest).clone())
}
async fn health_handler() -> &'static str {
"ok"
}