mirror of
https://github.com/block/buzz.git
synced 2026-10-31 22:41:12 +00:00
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>