@intuitionrobotics/thunderstorm
Version:
57 lines • 2.62 kB
JavaScript
import {} from "express";
import { handler } from "../../../../modules/server/handler.js";
import {} from "../../../../../shared/types.js";
import { Storm } from "../../../../core/Storm.js";
import { currentTimeMillies } from "@intuitionrobotics/ts-common";
import { isHealthCheckContributor } from "../../../../../shared/health.js";
const statusRank = { pass: 0, warn: 1, fail: 2 };
const worse = (a, b) => (statusRank[a] >= statusRank[b] ? a : b);
// Smart, transparent health endpoint — the raw-Express `handler(fn)` form.
//
// TRANSPARENT — the framework never injects this for you. Mount it explicitly
// from your routes file (one visible line), choosing your own path:
//
// import {healthHandler} from "@intuitionrobotics/thunderstorm/backend";
// v1.get("/health", healthHandler()); // or
// v1.get("/health", healthHandler({version}));
//
// SMART — it enumerates every loaded Storm module and reports env / node /
// uptime. Any module implementing HealthCheckContributor (getHealth())
// contributes real subsystem health; the overall status is the worst of them,
// and a "fail" is reflected as HTTP 503 so load balancers / uptime probes can
// gate on it.
export const healthHandler = (opts = {}) => handler(async (_req, res) => {
const storm = Storm?.getInstance();
const modules = storm ? storm.filterModules(() => true) : [];
const moduleHealth = await Promise.all(modules.map(async (module) => {
const name = module.getName();
if (!isHealthCheckContributor(module))
return { name, status: "pass" };
try {
const contribution = await module.getHealth();
return { name, status: contribution.status, detail: contribution.detail };
}
catch (e) {
return { name, status: "fail", detail: e?.message ?? "getHealth() threw" };
}
}));
const status = moduleHealth.reduce((worst, m) => worse(worst, m.status), "pass");
const report = {
status,
env: storm?.getEnvironment() ?? "unknown",
node: process.version,
uptimeSec: Math.floor(process.uptime()),
timestamp: currentTimeMillies(),
modules: moduleHealth,
version: opts.version
};
// A failing health check must surface as 503 (probes gate on it); writing
// res directly makes handler()'s autoSend a no-op. Otherwise return the
// report and autoSend emits 200.
if (status === "fail") {
res.status(503).json(report);
return;
}
return report;
}, { printResponse: false });
//# sourceMappingURL=get.js.map