30 lines
1.2 KiB
TypeScript
30 lines
1.2 KiB
TypeScript
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';
|
|
}
|