feat: add a readiness probe at /healthz #105
Inga granskare
Etiketter
Inga etiketter
area/backups
area/ci
area/control-panel
area/identity
area/infra
area/observability
area/payments
area/security
area/storage
area/web
blocked
needs-info
needs-triage
ready-for-implementation
type
bug
type
chore
type
docs
type
epic
type
feature
type
task
wontfix
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Inget förfallodatum satt.
Beroenden
Inga beroenden satta
Referens
bitborg/bitborg-web!105
Läser in…
Hänvisa till i nytt ärende
Ingen beskrivning angiven.
Ta bort grenen "feat/healthz"
Borttagning av en gren är permanent. Även om den borttagna grenen kan fortsätta existera en kort tid innan den faktiskt tas bort, kan det INTE ångras i de flesta fall. Vill du fortsätta?
Adds
GET /healthz, the prerequisite for gating deploys (#66). Nothing else in that issue — thecontainer healthcheck and
auto-update --rollback— can be built without something meaningful toprobe.
Why it checks the database
A static 200 would defeat the entire purpose. The deploy failures worth catching are exactly the ones
where the process starts fine and cannot serve: a wrong
DATABASE_URL, a failed migration, amissing secret. Verified against a real built server with
DATABASE_URLunset:GET /healthz{"db":"unreachable","ok":false}GET /The homepage still serves, because it does not touch Postgres. So a liveness-only probe — or a static
200 — would have reported that container healthy while sign-up was completely broken. That gap is the
whole reason for this endpoint.
Deliberate trade-off, and where the tolerance belongs
Including the database makes this a readiness probe, not a liveness probe: a Postgres blip marks
the portal unhealthy even though Node is fine. That is the right answer for "should this image be
promoted?" and the wrong answer for "should this container be killed?".
The consequence is that the container healthcheck needs enough retries that a transient blip cannot
trigger a pointless restart or a rollback of a perfectly good image. That tolerance belongs in the
Quadlet unit, not in this endpoint, and is called out in the code comment so it is not forgotten when
the infra side lands.
Shape
src/lib/health.ts— the logic, with the DB probe injected so it is testable without a livePostgres. Matches the repo's convention of logic in
lib/and thin pages.src/pages/healthz.ts— a thin route mapping the report to 200/503.Two details that matter:
hang until the healthcheck's own timeout killed it, which reports far less clearly than an explicit
503. The timer is always cleared, so a slow-but-successful probe leaves no pending handle.
this endpoint is public and unauthenticated. Only a coarse status is returned; the detail goes to the
container log. There is a test asserting the report cannot contain such text.
SELECT 1touches no application table, so the probe stays valid mid-migration.Verified
6 new tests (ok / rejects / hangs / slow-but-inside-deadline / no error leakage / timer cleared);
82 total, up from 76.
check,eslint,stylelint,format:check,mdlint,drizzle-kit checkand
buildall pass, plus the real-server check above.Refs #66