gate healthcheck on redis ready during cold start)

This commit is contained in:
Owen Greenhalgh
2026-05-26 10:12:28 +01:00
parent cddd2ce7a2
commit 48d9256666
2 changed files with 103 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
import { describe, expect, mock, test } from "bun:test";
import { EventEmitter } from "node:events";
class FakeRedis extends EventEmitter {
status: "wait" | "connecting" | "ready" | "end" = "wait";
setReady() {
this.status = "ready";
this.emit("ready");
}
}
const fakeRedis = new FakeRedis();
const fakeRedisV2 = new FakeRedis();
const fakeLogger = {
info: mock(() => undefined),
warn: mock(() => undefined),
error: mock(() => undefined),
debug: mock(() => undefined),
};
mock.module("@/external/redis/initRedis.js", () => ({ redis: fakeRedis }));
mock.module("@/external/redis/initRedisV2.js", () => ({
redisV2: fakeRedisV2,
}));
mock.module("@/external/logtail/logtailUtils.js", () => ({
logger: fakeLogger,
}));
const { handleHealthCheck } = await import("@/honoUtils/handleHealthCheck.js");
const callHealthCheck = async () => {
const responses: { status: number; body: string }[] = [];
const ctx = {
text: (body: string, status = 200) => {
responses.push({ status, body });
return { status, body };
},
};
await handleHealthCheck(
ctx as unknown as Parameters<typeof handleHealthCheck>[0],
);
return responses[0]!;
};
describe("handleHealthCheck startup gate", () => {
test("returns 503 when both Redis clients are not ready", async () => {
const res = await callHealthCheck();
expect(res.status).toBe(503);
expect(res.body).toBe("Redis not ready");
});
test("returns 503 when only one Redis client is ready", async () => {
fakeRedis.setReady();
const res = await callHealthCheck();
expect(res.status).toBe(503);
});
test("returns 200 once both Redis clients become ready", async () => {
fakeRedisV2.setReady();
const res = await callHealthCheck();
expect(res.status).toBe(200);
expect(res.body).toContain("Autumn");
});
test("logs a single latch info message on flip", async () => {
expect(fakeLogger.info).toHaveBeenCalledTimes(1);
const firstCall = fakeLogger.info.mock.calls[0] as unknown as [string];
expect(firstCall[0]).toContain("[health-check] startup gate latched");
});
test("returns 200 unconditionally after latch — even if Redis regresses", async () => {
fakeRedis.status = "end";
fakeRedisV2.status = "end";
const res = await callHealthCheck();
expect(res.status).toBe(200);
});
});