perf(measurements): insert fresh batch samples set-based; answer health while starting

POST /api/measurements/batch ran one interactive reconciler transaction
per fresh sample: a savepoint, three advisory locks, two candidate reads
and the insert, about ten round trips. A 500-entry upload of new samples
was 500 of those, the 2 to 15 second outliers. Fresh samples now land
through INSERT ... ON CONFLICT DO NOTHING under the same per-account
advisory lock. Both measurement identities are full unique indexes, so
the statement inserts exactly what the reconciler would have inserted,
and every skipped row still goes through the reconciler for its own
verdict. Only rows whose external and natural keys each occur once in
the batch are buffered, and the buffer is flushed before any other row
is reconciled, so the order of effects stays the sequential one. The
contract and every per-entry status are unchanged; a golden test runs
each batch through both paths against the same table.

/api/health took seconds after a start because register() awaited the
whole pg-boss worker start (queues, schedules, boot discovery) before
the server took a request. The worker, or a web process's producer, now
starts in the background after the blocking boot checks; the probe
answers at once with reason "starting" until it is up, and gives the
database two seconds before calling it not answering.
This commit is contained in:
Marc-André Bombeck committed 2026-10-21 20:42:06 +02:00
1 parent cc8ea3dfbb
commit 846b0e5df0
12 files changed
+835 -163

No files matched your search

+12 -7
View File
@@ -22852,8 +22852,9 @@ paths:
- $ref: "#/components/schemas/HealthAdminResponse"
- $ref: "#/components/schemas/HealthPublicResponse"
"503":
description: "Degraded — the database did not answer, or a role this process runs is not up. Same body shape as the 200,
with `status: \"degraded\"`. A restart loop reports this rather than failing to answer, so a monitor can
description: "Degraded — the database did not answer within two seconds, or a role this process runs is not up. Same
body shape as the 200, with `status: \"degraded\"`, and `reason: \"starting\"` while the background role is
still coming up after a start. A restart loop reports this rather than failing to answer, so a monitor can
tell 'starting' from 'gone'."
content:
application/json:
@@ -84210,14 +84211,18 @@ components:
when the process serves web, and the worker loop is running when the process runs the worker. `degraded` on any
of those failing."
HealthReason:
description: "Present only when the process refuses to serve for a reason a person has to fix.
`encryption_key_mismatch`: the configured encryption key cannot open the data in this database (checked at
boot). Every other route then answers 503 with `meta.errorCode` `encryption.key_mismatch`, and background jobs
are not started. Fix: restore the original key, point the server at the matching database, or start with an
empty one; then restart."
description: "Why a `degraded` process is degraded, when it is something other than a component failure.
`encryption_key_mismatch`: the process refuses to serve for a reason a person has to fix; the configured
encryption key cannot open the data in this database (checked at boot). Every other route then answers 503 with
`meta.errorCode` `encryption.key_mismatch`, and background jobs are not started. Fix: restore the original key,
point the server at the matching database, or start with an empty one; then restart. `starting`: the database
answers but the background role (the pg-boss worker, or the producer of a web-only process) is still coming up
after a start. Transient; nothing to fix, poll again. The probe answers at once while it lasts rather than
waiting for the start to finish."
type: string
enum:
- encryption_key_mismatch
- starting
HealthPublicResponse:
type: object
properties: