perf(eventcore-postgres): batch INSERT in append_events (#360) #406
No reviewers
Labels
No labels
adr
automated
bug
chore
dependencies
documentation
enhancement
epic
github-actions
P1-high
P2-medium
P3-low
release
research
rust
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Slipstream/eventcore!406
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "perf/360-postgres-batch-insert"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Replaces the per-event
INSERTloop inPostgresEventStore::append_eventswith a single multi-row INSERT per chunk, built viasqlx::QueryBuilderand chunked at 1000 events to stay well under Postgres' 65535 bound-parameter limit. For a 100-event append this turns 100 SQL round-trips into one statement.Correctness
The
BEFORE INSERTversion-assignment trigger is unchanged. It still assigns gap-free sequential versions and enforces optimistic concurrency per row in VALUES order. This was verified empirically against PostgreSQL 17: a multi-row INSERT fires theFOR EACH ROWtrigger per row in order, and each row's trigger sees the prior rows of the same statement (plpgsql advances the command snapshot between invocations), so versions and conflict detection behave identically to the per-row loop.The type-erased event payload (
Box<dyn Any>) is dropped before the insert loop — only the in-memory store needs it — so the borrows held across.awaitstaySend.Tests
Existing contract + internals tests (sequential version assignment, concurrent version conflicts, conflict-preserves-atomicity, cross-stream ordering) all pass. Adds an integration test that appends a 1200-event batch to a single stream (crossing the 1000-row chunk boundary) and reads it back.
Workflow note
Phases 1-3 are not applicable: behavior-preserving internal optimization, no public API change, acceptance criteria specified in the issue. Existing contract + integration tests are the regression safety net (Phase 4 TDD).
Closes #360
This PR optimizes the
append_eventsfunction inPostgresEventStoreby batching event inserts, reducing SQL round-trips and improving performance. The changes are well-tested and maintain existing functionality, making it safe to merge.Walkthrough
eventcore-postgres/src/lib.rs:
INSERTloop with a batched multi-rowINSERTusingsqlx::QueryBuilder.BEFORE INSERTtrigger behavior remains unchanged, ensuring sequential version assignment and conflict detection.StreamWriteEntrycould be removed for clarity.eventcore-postgres/tests/batch_append_test.rs:
BEFORE INSERTtrigger assigns gap-free sequential versions and that all events are stored durably.LLM usage and cost
Estimated total USD: $0.017809 via https://api.openai.com and https://api.openai.com