// Arcadia health probes. // // Backed by /api/v1/health* (public — no auth). Each subsystem is probed // independently; the overall endpoint aggregates and returns 503 if any // subsystem is not "ok". See arcadia-app commit f427892. import type { ArcadiaClient } from "@crema/arcadia-client" export type HealthSubsystem = "api" | "db" | "workers" | "storage" export type HealthStatus = "ok" | "degraded" | "error" | "unconfigured" export interface SubsystemHealth { status: HealthStatus /** Optional human-readable detail. */ message?: string /** Free-form metrics — shape is subsystem-specific. */ details?: Record } export interface OverallHealth { status: HealthStatus checked_at: string subsystems: Record } export interface DetailedHealth extends OverallHealth { /** BEAM info — present on /health/detailed only. */ system?: { otp_release?: string elixir_version?: string process_count?: number memory_total_bytes?: number [k: string]: unknown } } export interface HostStats { cpu: { util_pct: number | null per_cpu_pct: number[] load_avg_1: number | null load_avg_5: number | null load_avg_15: number | null schedulers_online: number num_cpus: number | null } memory: { total_bytes: number | null free_bytes: number | null available_bytes: number | null buffered_bytes: number | null cached_bytes: number | null swap_total_bytes: number | null swap_free_bytes: number | null } disks: Array<{ mount: string; total_kb: number; used_pct: number }> checked_at: string } const BASE = "/api/v1/health" export async function getHealth(arcadia: ArcadiaClient): Promise { const res = await arcadia.GET<{ data: OverallHealth } | OverallHealth>(BASE) return unwrap(res) } export async function getServiceHealth( arcadia: ArcadiaClient, service: HealthSubsystem, ): Promise { const res = await arcadia.GET<{ data: SubsystemHealth } | SubsystemHealth>( `${BASE}/${service}`, ) return unwrap(res) } export async function getHealthDetailed(arcadia: ArcadiaClient): Promise { const res = await arcadia.GET<{ data: DetailedHealth } | DetailedHealth>(`${BASE}/detailed`) return unwrap(res) } export async function getHostStats(arcadia: ArcadiaClient): Promise { const res = await arcadia.GET<{ data: HostStats } | HostStats>(`${BASE}/host`) return unwrap(res) } export const SUBSYSTEMS: HealthSubsystem[] = ["api", "db", "workers", "storage"] function unwrap(res: { data: T } | T): T { return res && typeof res === "object" && "data" in (res as object) ? (res as { data: T }).data : (res as T) }