From 01cd33a1135b224d180ebbbca61fee5a0f80f6e9 Mon Sep 17 00:00:00 2001 From: Ugooweb Date: Tue, 28 Jul 2026 15:32:45 +0100 Subject: [PATCH] feat: Add DB index for health lookup hot path [b#037] --- migrations/health_index.sql | 5 ++++ src/routes/health.ts | 60 ++++++++++++++++++++++++++----------- tests/health.test.ts | 50 +++++++++++++++++++++++++++---- 3 files changed, 92 insertions(+), 23 deletions(-) create mode 100644 migrations/health_index.sql diff --git a/migrations/health_index.sql b/migrations/health_index.sql new file mode 100644 index 0000000..782679c --- /dev/null +++ b/migrations/health_index.sql @@ -0,0 +1,5 @@ +-- up +CREATE INDEX IF NOT EXISTS idx_audit_logs_action_created_at ON audit_logs (action, created_at DESC); + +-- down +DROP INDEX IF NOT EXISTS idx_audit_logs_action_created_at; diff --git a/src/routes/health.ts b/src/routes/health.ts index c6e780b..5d2bab1 100644 --- a/src/routes/health.ts +++ b/src/routes/health.ts @@ -1,31 +1,55 @@ import { Router } from "express"; import { createAuditLog } from "../services/auditService"; import { getRequestId } from "../lib/requestContext"; +import { db } from "../db/client"; +import { auditLogs } from "../db/schema"; +import { eq, desc } from "drizzle-orm"; export const healthRouter = Router(); -// Mock memory state for demonstration purposes on health state -let currentHealthState = { mode: "active", maintenance: false }; +healthRouter.get("/", async (_req, res, next) => { + try { + const [latest] = await db + .select() + .from(auditLogs) + .where(eq(auditLogs.action, "health.state_mutation")) + .orderBy(desc(auditLogs.createdAt)) + .limit(1); -healthRouter.get("/", (_req, res) => { - res.json({ status: "ok", state: currentHealthState }); + const state = (latest?.afterState as Record) || { mode: "active", maintenance: false }; + res.json({ status: "ok", state }); + } catch (err) { + next(err); + } }); -healthRouter.post("/mutations", async (req, res) => { - const ip = req.ip || req.socket.remoteAddress || "unknown"; - const correlationId = getRequestId(); - const beforeState = { ...currentHealthState }; +healthRouter.post("/mutations", async (req, res, next) => { + try { + const ip = req.ip || req.socket.remoteAddress || "unknown"; + const correlationId = getRequestId(); - // Apply changes from body payload - currentHealthState = { ...currentHealthState, ...req.body }; + const [latest] = await db + .select() + .from(auditLogs) + .where(eq(auditLogs.action, "health.state_mutation")) + .orderBy(desc(auditLogs.createdAt)) + .limit(1); - await createAuditLog({ - action: "health.state_mutation", - ip, - correlationId, - beforeState, - afterState: currentHealthState, - }); + const beforeState = (latest?.afterState as Record) || { mode: "active", maintenance: false }; - res.json({ status: "updated", state: currentHealthState }); + // Apply changes from body payload + const afterState = { ...beforeState, ...req.body }; + + await createAuditLog({ + action: "health.state_mutation", + ip, + correlationId, + beforeState, + afterState, + }); + + res.json({ status: "updated", state: afterState }); + } catch (err) { + next(err); + } }); diff --git a/tests/health.test.ts b/tests/health.test.ts index 39e6190..4ee1d03 100644 --- a/tests/health.test.ts +++ b/tests/health.test.ts @@ -6,11 +6,51 @@ process.env.PREDICTIFY_CONTRACT_ID = "test-contract-id"; import request from "supertest"; import { createApp } from "../src/index"; +import { db } from "../src/db/client"; -describe("GET /health", () => { - it("returns ok status", async () => { - const res = await request(createApp()).get("/health"); - expect(res.status).toBe(200); - expect(res.body.status).toBe("ok"); +jest.mock("../src/db/client", () => ({ + db: { + select: jest.fn().mockReturnThis(), + from: jest.fn().mockReturnThis(), + where: jest.fn().mockReturnThis(), + orderBy: jest.fn().mockReturnThis(), + limit: jest.fn().mockResolvedValue([ + { afterState: { mode: "active", maintenance: false } } + ]), + }, + pool: { + query: jest.fn(), + }, +})); + +jest.mock("../src/services/auditService", () => ({ + createAuditLog: jest.fn().mockResolvedValue("mock-correlation-id"), +})); + +describe("healthRouter endpoints", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("GET /health", () => { + it("returns ok status and db state", async () => { + const res = await request(createApp()).get("/health"); + expect(res.status).toBe(200); + expect(res.body.status).toBe("ok"); + expect(res.body.state).toEqual({ mode: "active", maintenance: false }); + }); + }); + + describe("POST /health/mutations", () => { + it("updates health state and logs audit", async () => { + const res = await request(createApp()) + .post("/health/mutations") + .send({ mode: "maintenance", maintenance: true }); + + expect(res.status).toBe(200); + expect(res.body.status).toBe("updated"); + expect(res.body.state.mode).toBe("maintenance"); + expect(res.body.state.maintenance).toBe(true); + }); }); });