fix(clients/go): Nack placeholder, eager Connect ping, Consumer panic recovery#115
fix(clients/go): Nack placeholder, eager Connect ping, Consumer panic recovery#115
Conversation
Adds three failing tests, one per bug, to anchor red/green TDD: - TestNackPlaceholderCount: exercises Client.Nack against a live DB. Pre-fix pgx errors with 'expected 12 arguments, got 11' because the ROW(...) cast targeting pgque.message (10 fields) has a trailing $12 typo while only 11 args are supplied. - TestConnect_UnreachableHostFailsImmediately: dials port 1 (reserved, refuses connections). Pre-fix Connect returns nil error within microseconds because pgxpool.New is lazy. Post-fix it errors on pool.Ping within ~3s. - TestConsumer_HandlerPanicRecoversAndContinues: handler panics on the first message, succeeds on the second. Pre-fix the panic kills the consumer goroutine; the second message never reaches its handler. Post-fix the consumer recovers, nacks the panicking message, and keeps polling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pgque.message has 10 fields (msg_id … extra4); the ROW() cast in Nack() had 11 placeholders ($2..$12) and 11 args — one extra. Trim to $2..$11 so the placeholder count equals the field count. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pgxpool.New is lazy and never dials; Connect now calls pool.Ping so unreachable hosts fail at call-site, not on the first query. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrap each handler dispatch in dispatchWithRecover; a panic is caught by defer/recover, converted to an error, and the message is nack'd so it retries. The poll loop continues to the next msg. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Lower ticker thresholds per-queue so tests don't wait 3 s for a tick. Teardown opens a fresh pool to avoid use-after-close when defer client.Close() fires before t.Cleanup; purge retry_queue and dead_letter rows before drop_queue to prevent stale leaks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
REV Review — PR #115CI: green — Functional evidence: Reviewed the post-fix files on Verdict: READY FOR USER REVIEW Blocking
Non-blocking
Potential
Summary
Anti-leak: clean — no GitLab/internal/benchmark-WI references in diff, commits, title, or body. REV-style review (security, bugs, tests, guidelines, docs). SOC2 items skipped per project policy. |
Remove TestConnect_UnreachableHost and TestConsumer_HandlerPanicKillsLoop; both document pre-#115 behavior (lazy Connect, panic kills loop) that the bugfix PR corrected and re-tested with TestConnect_UnreachableHostFailsImmediately and TestConsumer_HandlerPanicRecoversAndContinues. Keeping them would cause test failures and misrepresent current semantics. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…edge cases, benchmarks (#81) * test(clients/go): comprehensive coverage suite Add 6 new test files covering the Go driver beyond the happy path: - helpers_test.go (115 LOC) — shared connectOrSkip, setupFreshQueue with unique random suffixes per test, retryQueueCount, dlqCount helpers - integration_test.go (231 LOC) — multi-event batches, max-batch limits, empty-queue receive, payload round-trip, default event type, DLQ-at-limit - errors_test.go (208 LOC) — bad DSN, unreachable host, missing queue, missing consumer, after-close panic-safety on Send/Receive/Ack/Nack, context cancellation, unmarshalable payload (chan) - consumer_test.go (239 LOC) — clean Start/Stop, poll-interval respected, unregistered-event nack, context propagation to handler, single-ack- per-batch, documents current handler-panic behavior (kills goroutine) - concurrency_test.go (272 LOC) — concurrent Send under -race, full send/receive/ack loop, handler-nack-under-load, two consumers same queue, double-Start safety - edge_test.go (262 LOC) — empty payload, 1 MiB payload, unicode (CJK + emoji), special-char event types, timestamp sanity, retry_count initial state, string + array payload shapes - bench_test.go (169 LOC) — BenchmarkSend, BenchmarkReceive_Empty, BenchmarkSendReceiveAck, BenchmarkConsumer_DispatchThroughput All integration tests env-gated via PGQUE_TEST_DSN; t.Skip when unreachable. Each test uses a uniquely-named queue + consumer with t.Cleanup so parallel runs cannot collide. Verified: go build ./... clean, go vet ./... clean, gofmt -l clean. Live integration runs require PGQUE_TEST_DSN; not exercised in this commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(clients/go): drop stale tests superseded by #115 Remove TestConnect_UnreachableHost and TestConsumer_HandlerPanicKillsLoop; both document pre-#115 behavior (lazy Connect, panic kills loop) that the bugfix PR corrected and re-tested with TestConnect_UnreachableHostFailsImmediately and TestConsumer_HandlerPanicRecoversAndContinues. Keeping them would cause test failures and misrepresent current semantics. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(clients/go): strengthen weak assertions - TestSend_MissingQueue: t.Logf → t.Errorf for queue/not-found check - TestSend_ContextCancelled: t.Logf → t.Errorf for context.Canceled wrap - TestRace_HandlerNackUnderLoad: t.Logf → t.Errorf on failed==0 - TestNack_ToDLQAtRetryLimit: remove Ack-after-Nack (mutually exclusive on same batch); raise cycles to 5; t.Skipf → t.Fatalf on dlqCount==0 - TestSend_AfterClose / TestReceive_AfterClose: use a second live client for cleanup so t.Cleanup does not run on a closed pool * test(clients/go): rename tests and fix helpers - TestConsumer_AckOnlyOnceForBatch → TestConsumer_AllMessagesDispatched (body counts handler calls, not Ack invocations) - TestConsumer_PollIntervalRespected → TestConsumer_LivenessUnderEmptyQueue (body tests liveness, not measured cadence) - TestConsumer_StartTwiceFromSameInstance → TestConsumer_DoubleStart_DoesNotPanic (scope is limited to no-panic guarantee) - TestConcurrent_TwoConsumersSameQueue → TestConcurrent_TwoConsumersDistinctNames using distinct consumer registrations; assert each sees all messages - benchSuffix: replace time+name suffix with crypto/rand (collision-safe) - helpers_test.go: correct stale comment about Connect laziness - Remove PR-number references from source comments --------- Co-authored-by: Nik Samokhvalov <nik@niks-mbp.lan> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes #91.
Bugs fixed
Three regressions caught by red tests written in commit
672615b.Nack()SQL had 11 placeholders ($2..$12) butpgque.messagehas 10 fields — pgx rejected the query with428466d7b04aConnect()calledpgxpool.New(lazy) and returnednilerror for unreachable hosts — failure only surfaced on the first querybc4a2b9Consumer.Startkilled the poll goroutine and stalled the queue — subsequent messages were never delivered0102cafA fourth commit (
7f2797d) improves test setup/teardown: lowers per-queue ticker thresholds, opens a fresh pool for cleanup to avoid use-after-close, and purgesretry_queue/dead_letterrows beforedrop_queue.Full
go testoutput (local PG, all green)Anti-leak confirmation
No internal GitLab, prospect, or benchmark work-item references in any changed file.