Refactor health checks to use effects.fetch and util helpers

This commit is contained in:
satoshi
2026-05-10 17:24:52 +03:00
parent c71309844b
commit c925dceecc
+24 -42
View File
@@ -1,6 +1,7 @@
import { healthUtil, types as T } from "../deps.ts"; import { healthUtil, util, types as T } from "../deps.ts";
const API_BASE = "http://kamado-pool.embassy:8080"; const API_BASE = "http://kamado-pool.embassy:8080";
const STARTING_GRACE_MS = 20_000;
interface HealthPayload { interface HealthPayload {
ok: boolean; ok: boolean;
@@ -11,65 +12,46 @@ interface HealthPayload {
last_error?: string; last_error?: string;
} }
async function fetchHealth(): Promise<HealthPayload | null> { async function fetchHealth(effects: T.Effects): Promise<HealthPayload | null> {
try { try {
const res = await fetch(`${API_BASE}/api/health`, { const res = await effects.fetch(`${API_BASE}/api/health`);
signal: AbortSignal.timeout(5_000),
});
return await res.json() as HealthPayload; return await res.json() as HealthPayload;
} catch { } catch {
return null; return null;
} }
} }
// Returns a "starting" result for the first 20 s after launch, then
// "failing" so a crashed service doesn't look like it's perpetually booting.
function apiUnreachable(duration: number, label: string): T.HealthProceduralResult {
if (duration < 20_000) {
return { status: "starting", message: `${label} is starting…` };
}
return { status: "failing", message: "Kamado API is unreachable — service may be down." };
}
export const health: T.ExpectedExports.health = { export const health: T.ExpectedExports.health = {
// Overall reachability: uses the SDK helper so StartOS marks the
// service degraded (503) whenever ckpool or bitcoind is down.
"web": async (effects, duration) => { "web": async (effects, duration) => {
return healthUtil.checkWebUrl(`${API_BASE}/api/health`)(effects, duration); return healthUtil.checkWebUrl(`${API_BASE}/api/health`)(effects, duration);
}, },
// Is the stratum server up and accepting miner connections? "ckpool": async (effects, duration) => {
"ckpool": async (_effects, duration) => { if (duration < STARTING_GRACE_MS) return util.errorCode(60, "Stratum server is starting…");
const h = await fetchHealth(); const h = await fetchHealth(effects);
if (!h) return apiUnreachable(duration, "Stratum server"); if (!h) return util.error("Kamado API is unreachable — service may be down.");
if (h.ckpool) return { status: "passing", message: "Stratum server is running." }; if (h.ckpool) return util.ok;
const detail = h.last_error ? ` (${h.last_error})` : ""; const detail = h.last_error ? ` (${h.last_error})` : "";
return { status: "failing", message: `Stratum server is not responding${detail}.` }; return util.error(`Stratum server is not responding${detail}.`);
}, },
// Can we reach Bitcoin Core via RPC? (Required for block templates and "bitcoin": async (effects, duration) => {
// block submission — if this is down, mining produces no valid work.) if (duration < STARTING_GRACE_MS) return util.errorCode(60, "Bitcoin Core connection is starting…");
"bitcoin": async (_effects, duration) => { const h = await fetchHealth(effects);
const h = await fetchHealth(); if (!h) return util.error("Kamado API is unreachable — service may be down.");
if (!h) return apiUnreachable(duration, "Bitcoin Core connection"); if (h.bitcoin) return util.ok;
if (h.bitcoin) return { status: "passing", message: "Connected to Bitcoin Core." };
const detail = h.last_error ? ` (${h.last_error})` : ""; const detail = h.last_error ? ` (${h.last_error})` : "";
return { status: "failing", message: `Bitcoin Core RPC is unreachable${detail}.` }; return util.error(`Bitcoin Core RPC is unreachable${detail}.`);
}, },
// Did every block submission get confirmed by bitcoind? A non-zero gap "submit-gap": async (effects, duration) => {
// means at least one "Possible block solve" never got a "Solved and if (duration < STARTING_GRACE_MS) return util.errorCode(60, "Block submission check is starting…");
// confirmed" response — the reward may have been lost or delayed. const h = await fetchHealth(effects);
"submit-gap": async (_effects, duration) => { if (!h) return util.error("Kamado API is unreachable — service may be down.");
const h = await fetchHealth();
if (!h) return apiUnreachable(duration, "Block submission check");
const gap = h.submit_gap ?? 0; const gap = h.submit_gap ?? 0;
if (gap === 0) return { status: "passing", message: "All block submissions confirmed." }; if (gap === 0) return util.ok;
return { return util.error(
status: "failing", `${gap} block${gap === 1 ? "" : "s"} submitted to bitcoind but not confirmed — check Bitcoin Core logs.`,
message: );
`${gap} block${gap === 1 ? "" : "s"} submitted to bitcoind but not confirmed — ` +
`check Bitcoin Core logs for rejected or missing submissions.`,
};
}, },
}; };