upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/http_health.rs
diff options
context:
space:
mode:
authorYour Name <you@example.com>2026-05-26 18:01:30 +0530
committerYour Name <you@example.com>2026-05-26 18:01:30 +0530
commite435f7d7b4ad4e4b1d3c21c35df5f41ffd642376 (patch)
treeccb0587d8aff2d0513f2cef359349b6e0b1b947f /src/http_health.rs
parent8816a192c95cf539b65975469a2d61aed46f0414 (diff)
Add HTTP health endpoint on /health and /api/mirror-health
- New axum-based health server on port 7335 (configurable via health_port) - Reports status, uptime, cycle_count, last_cycle_ok as JSON - Status is 'ok' on startup and after successful cycles, 'degraded' after failures - Config: storage.health_port defaults to 7335 - Spawned alongside daemon loop, independent of mirror cycles
Diffstat (limited to 'src/http_health.rs')
-rw-r--r--src/http_health.rs40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/http_health.rs b/src/http_health.rs
new file mode 100644
index 0000000..0cdfeb5
--- /dev/null
+++ b/src/http_health.rs
@@ -0,0 +1,40 @@
1use axum::extract::State;
2use axum::response::Json;
3use axum::routing::get;
4use axum::Router;
5use serde_json::{json, Value};
6use std::sync::Arc;
7use std::time::Instant;
8use tokio::sync::watch;
9
10pub struct HealthState {
11 pub started_at: Instant,
12 pub cycle_count: watch::Receiver<u64>,
13 pub last_cycle_ok: watch::Receiver<bool>,
14 pub db_path: String,
15}
16
17pub async fn start_health_server(port: u16, state: Arc<HealthState>) -> anyhow::Result<()> {
18 let app = Router::new()
19 .route("/health", get(health_handler))
20 .route("/api/mirror-health", get(health_handler))
21 .with_state(state);
22
23 let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{}", port)).await?;
24 tracing::info!(port, "health server listening");
25 axum::serve(listener, app).await?;
26 Ok(())
27}
28
29async fn health_handler(State(state): State<Arc<HealthState>>) -> Json<Value> {
30 let uptime = state.started_at.elapsed();
31 let cycle_count = *state.cycle_count.borrow();
32 let last_ok = *state.last_cycle_ok.borrow();
33
34 Json(json!({
35 "status": if last_ok || cycle_count == 0 { "ok" } else { "degraded" },
36 "uptime_secs": uptime.as_secs(),
37 "cycle_count": cycle_count,
38 "last_cycle_ok": last_ok,
39 }))
40}