Files
buzz/crates/buzz-relay
tlongwell-block 686b010b3f feat(relay): group-commit batching for plain event inserts
At high ingest rates each plain event pays a full synchronous COMMIT
(WAL flush; storage-quorum ack on Aurora). A single writer task now
coalesces concurrent inserts into one transaction so one commit
amortizes over the whole batch, while each caller keeps its own
per-event result.

Design (buzz_db::batch):
- Opportunistic, not timed: the worker takes one request then drains
  whatever else is queued (up to BUZZ_WRITE_BATCH_MAX, default 16).
  A lone request under light load flushes immediately via the direct
  path — zero added latency; batches only form while a previous
  transaction is committing.
- ACK-after-commit: a caller's future resolves only after the
  transaction containing its event durably committed.
- Poison isolation, statement time: savepoint per event; a failing
  statement (FK violation, rejected kind) fails only that event.
- Poison isolation, commit time: deferred constraint triggers
  (0021/0022) fire during COMMIT after savepoints are gone, so one bad
  row aborts the batch. A server-reported COMMIT error (SQLSTATE
  present — provable abort) replays every request individually through
  the unbatched path so the poison fails alone.
- Indeterminate commits are not replayed: a transport failure awaiting
  the COMMIT response may have committed server-side; a blind replay
  would misreport durable inserts as duplicates and skip their
  mentions. Callers get DbError::CommitOutcomeUnknown; client retries
  are idempotent (ON CONFLICT DO NOTHING).
- Mentions stay post-commit on the pool, log-and-succeed, per event —
  exactly matching the unbatched wrapper.
- Degradation: a dead worker makes the batcher handle return None and
  ingest falls through to today's direct path; it never hangs a future.

Relay wiring: BUZZ_WRITE_BATCH_MAX env knob (0 disables, state holds
Option<EventWriteBatcher>); only the plain persistent-event branch
routes through the batcher — kind:9007 channel-create, replaceables,
and reactions stay direct. Coalescing counters exported as
buzz_write_batch_* Prometheus counters from the existing pool-metrics
poller; committed vs. fallback vs. indeterminate are distinguishable
by construction.

Tests (PG-backed, #[ignore]): mixed batch (good / in-batch duplicate /
FK poison / rejected AUTH kind / threaded replies) with per-event
result pinning and exact thread counters; deferred-trigger abort →
per-event replay; commit-error classification; dead-worker fallback;
64-way concurrent coalescing with committed-before-ACK asserted from a
second connection.

Co-authored-by: Dawn (sprout agent) <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
2026-07-19 18:44:21 -04:00
..