← back to Homesonspec
apps/workers/src/health-server.test.ts
95 lines
import { afterEach, describe, expect, it } from "vitest";
import http from "node:http";
import type { AddressInfo } from "node:net";
import { startHealthServer, closeHealthServer } from "./health-server";
/**
* Regression coverage for the 2026-08-09 prod incident: the worker crash-looped
* because healthServer.listen() had no 'error' handler, so an EADDRINUSE bind
* failure on the shared host became an uncaughtException. A health probe is
* auxiliary — its bind failure must NEVER crash the worker.
*/
const opened: http.Server[] = [];
afterEach(() => {
for (const s of opened) {
try {
if (s.listening) s.close();
} catch {
/* ignore */
}
}
opened.length = 0;
});
function listenReady(server: http.Server): Promise<number> {
return new Promise((resolve, reject) => {
server.once("error", reject);
server.once("listening", () => resolve((server.address() as AddressInfo).port));
});
}
function get(port: number): Promise<{ status: number; body: string }> {
return new Promise((resolve, reject) => {
http
.get({ host: "127.0.0.1", port, path: "/health" }, (res) => {
let body = "";
res.on("data", (c) => (body += c));
res.on("end", () => resolve({ status: res.statusCode ?? 0, body }));
})
.on("error", reject);
});
}
describe("startHealthServer", () => {
it("serves 200 + verdict on /health when healthy", async () => {
const server = startHealthServer({ port: 0, host: "127.0.0.1", health: () => ({ healthy: true, reason: "ok" }) });
opened.push(server);
const port = await listenReady(server);
const res = await get(port);
expect(res.status).toBe(200);
expect(JSON.parse(res.body)).toEqual({ healthy: true, reason: "ok" });
});
it("serves 503 when the queue verdict is unhealthy", async () => {
const server = startHealthServer({
port: 0,
host: "127.0.0.1",
health: () => ({ healthy: false, reason: "wedged" }),
});
opened.push(server);
const port = await listenReady(server);
const res = await get(port);
expect(res.status).toBe(503);
expect(JSON.parse(res.body).healthy).toBe(false);
});
it("a bind failure (EADDRINUSE) is NON-FATAL — logs and continues, never throws", async () => {
// Occupy a port first.
const blocker = http.createServer();
opened.push(blocker);
const takenPort = await new Promise<number>((resolve) =>
blocker.listen(0, "127.0.0.1", () => resolve((blocker.address() as AddressInfo).port)),
);
const errors: string[] = [];
// Starting the health server on the SAME port must not throw or crash.
const server = startHealthServer({
port: takenPort,
host: "127.0.0.1",
health: () => ({ healthy: true, reason: "ok" }),
errorLog: (...a) => errors.push(a.map(String).join(" ")),
});
opened.push(server);
// The 'error' event is async; give the event loop a tick to deliver it.
await new Promise((r) => setTimeout(r, 50));
expect(server.listening).toBe(false); // never bound (port taken)...
expect(errors.some((e) => /failed to bind/.test(e))).toBe(true); // ...but handled, not thrown.
// Reaching this line at all proves the process did not crash.
// closeHealthServer must be safe on a server that never bound:
expect(() => closeHealthServer(server)).not.toThrow();
});
});