import { freshStatusTimestamp } from '../../server-freshness.js'; export type Health = 'online' | 'stale' | 'offline' | 'starting' | 'provisioning'; const STALE_MAX_MS = 120_000; /** * Classify server health from its last successful RCON timestamp. * `offline` if we've never seen it or the last successful reply is >120s old. * `stale` on a blocking RCON failure or if the last reply is >90-120s old. * `online` if fresh, including the allowance for polling and delivery. */ export function classifyHealth(lastSeenAt: string | null, lastError: string | null, containerState?: string | null): Health { if (containerState === 'starting' || containerState === 'restarting') return 'starting'; if (containerState && containerState !== 'running' && containerState !== 'unknown') return 'offline'; if (!lastSeenAt) return 'offline'; const age = Date.now() - new Date(lastSeenAt).getTime(); if (freshStatusTimestamp(lastSeenAt, Date.now())) { // Even with a fresh last_seen, a very recent error demotes to stale return lastError ? 'stale' : 'online'; } if (!Number.isFinite(age) || age < 0) return 'offline'; if (age <= STALE_MAX_MS) return 'stale'; return 'offline'; }