feat(clients): expose atomic batch send#161
Conversation
REV Code Review Report
BLOCKING ISSUES (3)HIGH
HIGH
HIGH
NON-BLOCKING (4)HIGH
HIGH
MEDIUM
MEDIUM
POTENTIAL ISSUES (3)MEDIUM
LOW
LOW
Summary
REV-assisted review (AI analysis by postgres-ai/rev) |
b2f2b65 to
3659a2c
Compare
REV Code Review Report
BLOCKING ISSUES (8)HIGH
HIGH
HIGH
HIGH
HIGH
HIGH
HIGH
HIGH
NON-BLOCKING (7)HIGH
MEDIUM
MEDIUM
MEDIUM
MEDIUM
LOW
LOW
POTENTIAL ISSUES (5)HIGH
HIGH
MEDIUM
MEDIUM
LOW
Summary
REV-assisted review (AI analysis by postgres-ai/rev) |
REV Code Review Report
BLOCKING ISSUES (14)GuidelinesHIGH
Tests — Go
|
| Area | Blocking | Potential | Filtered |
|---|---|---|---|
| CI | — | — | — |
| Security | 0 | 0 | 1 |
| Bugs | 0 | 2 | 2 |
| Tests | 10 | 0 | 1 |
| Guidelines | 1 | 1 | 2 |
| Docs | 3 | 1 | 2 |
The new SendBatch/sendBatch APIs are cleanly designed and the happy-path tests pass. The main concerns are test coverage parity with Send in both Go and TypeScript (the project's own TDD rule applies here), two documentation regressions in the Python client (a stripped API-contract docstring and a stripped regression-bug explanation), and one style violation (uppercase SELECT in new Go SQL).
REV-assisted review (AI analysis by postgres-ai/rev)
REV Code Review Report
BLOCKING ISSUES (2)MEDIUM
MEDIUM
NON-BLOCKING (5)MEDIUM
LOW
LOW
LOW
INFO
POTENTIAL ISSUES (8)MEDIUM
MEDIUM
MEDIUM
MEDIUM
LOW
LOW
LOW
LOW
Summary
REV-assisted review (AI analysis by postgres-ai/rev) |
REV Code Review Report
POTENTIAL ISSUES (7)LOW
LOW
LOW
LOW
LOW
LOW
LOW
Summary
No blocking issues. Implementation, error handling, and test coverage are sound. The atomic-batch contract is consistent across Go/TypeScript/Python, and benchmarks fail loud on count mismatch. Items above are quality-of-life polish. REV-assisted review (AI analysis by postgres-ai/rev) |
|
Final testing / review evidence for latest head Rebased on latest Local verification: cd clients/typescript
bun run check
PGQUE_TEST_DSN=postgresql://postgres:pgque_test@localhost/pgque_batch_test bun run test
PGQUE_TEST_DSN=postgresql://postgres:pgque_test@localhost/pgque_batch_test bun src/smoke.ts
PGQUE_TEST_DSN=postgresql://postgres:pgque_test@localhost/pgque_batch_test bun run bench:producer
cd ../..
PGQUE_TEST_DSN=postgresql://postgres:pgque_test@localhost/pgque_batch_test /tmp/pgque-pr161-venv/bin/pytest -q clients/python/tests/test_send.py clients/python/tests/test_smoke.py
PGQUE_TEST_DSN=postgresql://postgres:pgque_test@localhost/pgque_batch_test /tmp/pgque-pr161-venv/bin/python clients/python/bench_producer.pyResults:
CI:
REV:
|
REV Code Review Report
BLOCKING ISSUES (2)HIGH `clients/go/pgque_test.go:260-271` — TestSendBatch payload-order assertion will flake
MEDIUM `clients/go/pgque.go:187` — "inside the caller's transaction" is misleading
NON-BLOCKING (3)INFO `clients/typescript/src/client.ts:104` — `sendBatch` JSDoc is a bare one-liner
INFO `clients/go/README.md:1-5` — `SendBatch` not mentioned in package prose
INFO `clients/typescript/README.md:66` — "event ids" casing inconsistent
POTENTIAL ISSUES (7)MEDIUM `clients/python/bench_producer.py:74-77` — `finally` block can mask original exception (confidence: 7/10)
MEDIUM `clients/typescript/src/producer_bench.ts:122-127` — `median([])` returns `undefined` when all iterations fail (confidence: 7/10)
MEDIUM `clients/python/pgque/client.py:158` — new `send_batch` docstring drops explicit empty-list and required-`type` behavior (confidence: 7/10)
MEDIUM `clients/typescript/src/client.ts:114` — `undefined` payload entries silently become JSON `null` with no test (confidence: 7/10)
LOW `clients/go/pgque_test.go:332` — `TestSendBatchMissingQueue` only asserts `err != nil` (confidence: 7/10)
LOW `clients/python/tests/test_send.py` — no test for `send_batch` with an empty list (confidence: 6/10)
LOW Commit `3659a2c` — subject is 57 characters, 7 over the 50-char limit (confidence: 9/10)
Summary
REV-assisted review (AI analysis by postgres-ai/rev) |
REV Code Review Report
BLOCKING ISSUES (0)No blocking issues found. NON-BLOCKING (7)MEDIUM
MEDIUM
MEDIUM
MEDIUM
LOW
LOW
LOW
POTENTIAL ISSUES (4)MEDIUM
LOW
LOW
LOW
Summary
REV-assisted review (AI analysis by postgres-ai/rev) |
Summary
Expose atomic batch send as a first-class producer API in Go and TypeScript, document the existing Python batch API, and add comparable producer benchmarks for all three client libraries.
This PR is about the final client interfaces: application code should not need to hand-roll loops over
send()when it wants to publish many messages as one logical batch.Before
Python had a batch method:
But Go and TypeScript users had to write loops over
send():Problems:
pgque.send_batch(...)exists.After
Go:
TypeScript:
Python docs now show the already-existing equivalent:
All three point at the same SQL-level contract:
Contract
A batch is one logical publish operation:
default;If a payload cannot be encoded or the database rejects the call, no partial batch is reported as successful.
Why this is better
1. Batch is visible in all final client interfaces
Batching becomes a normal producer operation, not something only SQL/Python users discover.
2. The API matches the actual product model
sendBatch/send_batch/SendBatchmirrors the existing safe SQL API instead of exposing table internals.3. Atomicity is explicit
The client docs/comments say the important part plainly: the call is all-or-nothing inside the caller's transaction.
4. It removes client-side loops from the happy path
Go/TS users can make one call and let PgQue handle the batch boundary.
5. It composes with #159 instead of competing with it
This PR intentionally uses the existing same-type SQL shape:
If/when #159 (or its successor from #160) makes
send_batch()set-based internally, these client APIs automatically benefit without changing public interfaces.Producer benchmarks
Added env-gated producer benchmarks for all three clients:
clients/python/bench_producer.pyTestProducerBenchmarksgated byPGQUE_RUN_PRODUCER_BENCH=1bun run bench:producerEach benchmark compares:
loop over send(): loop oversend()/Send()/client.send();send_batch()/SendBatch()/sendBatch();for batch sizes 1, 100, 1000. Each measurement creates a fresh queue, publishes N events, verifies inserted row count, drops the queue, and reports median latency + events/sec over 3 repeats.
Latest GitHub Actions
client-smokebenchmark results (PostgreSQL 18 runner):Relationship to #159 and #160
This PR does not rewrite server-side
send_batch().send_batch()set-based.send_batch()is the safe high-level batch API; directcurrent_event_table()/ COPY remains the expert max-throughput path.Intended layering:
send()— simple single-message API.sendBatch/send_batch/SendBatch— safe high-level app batching.current_event_table()insert/COPY — expert throughput path.Changed files
Client.SendBatch(ctx, queue, type, payloads)client.sendBatch(queue, type, payloads)send_batch(...)client-smokeruns all three producer benchmarks and prints tables in logs.Tests
Latest evidence is posted in comments after the final rebase/fixes:
claude-review,client-smoke, PG 14–18 matrix,verifybun run checkPGQUE_TEST_DSN=... bun run test→ 28 passedPGQUE_TEST_DSN=... bun src/smoke.tsPGQUE_TEST_DSN=... bun run bench:producerPGQUE_TEST_DSN=... pytest -q clients/python/tests/test_send.py clients/python/tests/test_smoke.py→ 20 passedPGQUE_TEST_DSN=... python clients/python/bench_producer.pygobinary is installed; GitHubclient-smokecovers Go and passed.