From 5b05fd4730eebc0f17825ffea49fdbfeb8efae95 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 2 Jun 2026 22:53:39 +1000 Subject: [PATCH] feat(health): service_status cache table + repo --- lib/db/migrations/014_service_status.sql | 8 ++++++++ lib/db/repos/service_status.js | 14 ++++++++++++++ tests/repos/service_status.test.js | 14 ++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 lib/db/migrations/014_service_status.sql create mode 100644 lib/db/repos/service_status.js create mode 100644 tests/repos/service_status.test.js diff --git a/lib/db/migrations/014_service_status.sql b/lib/db/migrations/014_service_status.sql new file mode 100644 index 0000000..483dfad --- /dev/null +++ b/lib/db/migrations/014_service_status.sql @@ -0,0 +1,8 @@ +-- 014_service_status.sql +CREATE TABLE service_status ( + service_id text PRIMARY KEY, + status text NOT NULL CHECK (status IN ('ok','warn','down','unknown')), + latency_ms integer, + detail text, + checked_at timestamptz NOT NULL DEFAULT now() +); diff --git a/lib/db/repos/service_status.js b/lib/db/repos/service_status.js new file mode 100644 index 0000000..af499b2 --- /dev/null +++ b/lib/db/repos/service_status.js @@ -0,0 +1,14 @@ +import { pool } from '../pool.js'; +export async function upsert({ service_id, status, latency_ms = null, detail = null }) { + await pool.query( + `INSERT INTO service_status (service_id, status, latency_ms, detail, checked_at) + VALUES ($1,$2,$3,$4, now()) + ON CONFLICT (service_id) DO UPDATE + SET status=EXCLUDED.status, latency_ms=EXCLUDED.latency_ms, + detail=EXCLUDED.detail, checked_at=now()`, + [service_id, status, latency_ms, detail]); +} +export async function all() { + const { rows } = await pool.query(`SELECT * FROM service_status`); + return rows; +} diff --git a/tests/repos/service_status.test.js b/tests/repos/service_status.test.js new file mode 100644 index 0000000..0fb691b --- /dev/null +++ b/tests/repos/service_status.test.js @@ -0,0 +1,14 @@ +import { describe, it, expect, beforeAll } from 'vitest'; +import { resetDb } from '../helpers/db.js'; +import { migrateUp } from '../../lib/db/migrate.js'; +import * as repo from '../../lib/db/repos/service_status.js'; + +beforeAll(async () => { await resetDb(); await migrateUp(); }); +describe('service_status repo', () => { + it('upserts and reads all', async () => { + await repo.upsert({ service_id: 'gitea', status: 'ok', latency_ms: 12, detail: '200' }); + await repo.upsert({ service_id: 'gitea', status: 'down', latency_ms: null, detail: 'ECONN' }); + const all = await repo.all(); + expect(all.find(r => r.service_id === 'gitea').status).toBe('down'); + }); +});