Skip to content

feat: DLQ support, error classification, and retry tracking#7

Merged
jamesdube merged 1 commit intomainfrom
feat/dlq-retry-error-handling
Feb 27, 2026
Merged

feat: DLQ support, error classification, and retry tracking#7
jamesdube merged 1 commit intomainfrom
feat/dlq-retry-error-handling

Conversation

@jamesdube
Copy link
Owner

Summary

  • Add error classification types (PermanentError, TransientError) with IsPermanent()/IsTransient() helpers for consumer error routing
  • Add DLQ infrastructure: dead-letter exchange ({exchange}.dlx) + DLQ queue ({queue}.dlq) auto-declared on consumer setup
  • Add ConsumerConfig struct and NewConsumerWithOptions() constructor for full control over retry/DLQ/prefetch behaviour
  • Implement retry tracking via x-retry-count AMQP header with exponential backoff (capped at 30s)
  • Add panic recovery in handler — panics become PermanentError and route to DLQ
  • Fix Ack(true)/Nack(true, ...) multiple=true bug that could ACK/NACK unprocessed messages when prefetch > 1

Error routing logic

Error type Behaviour
PermanentError Route to DLQ immediately, ACK original
TransientError / unclassified (retries < max) Republish with incremented x-retry-count, exponential backoff, ACK original
Unclassified (retries >= max) Route to DLQ, ACK original
Handler panic Wrapped as PermanentError → DLQ

Backward compatibility

  • NewConsumer() and NewConsumerWithConfig() unchanged — DLQ disabled by default
  • Existing consumers get Nack(false, true) (requeue) on error, same as before but with the multiple=false fix

Test plan

  • 12 new unit tests for error types, header parsing, config defaults, and header copying
  • All existing tests pass with -race
  • Integration test with live RabbitMQ to verify DLQ routing end-to-end

🤖 Generated with Claude Code

…c recovery

Add robust error handling to the consumer with three error categories:
- PermanentError: routes immediately to DLQ (e.g. malformed payloads)
- TransientError: retries with exponential backoff
- Unclassified: retries up to MaxRetries, then routes to DLQ

Key changes:
- New ConsumerConfig struct and NewConsumerWithOptions constructor
- DLQ infrastructure (dead-letter exchange + queue per consumer)
- Retry tracking via x-retry-count AMQP header
- Panic recovery in handler (panics become PermanentError)
- Fix ACK/NACK multiple=true bug (was true, now false to avoid
  acknowledging unprocessed messages with prefetch)
- Fully backward compatible: NewConsumer/NewConsumerWithConfig unchanged

12 new tests, all passing with -race.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jamesdube jamesdube merged commit b6fc4d0 into main Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant