Skip to content

feat: dead letter mechanism for non-retryable messages#77

Merged
cbartz merged 36 commits into
mainfrom
feat/dead-letter-ISD-4906
Jan 12, 2026
Merged

feat: dead letter mechanism for non-retryable messages#77
cbartz merged 36 commits into
mainfrom
feat/dead-letter-ISD-4906

Conversation

@cbartz

@cbartz cbartz commented Jan 7, 2026

Copy link
Copy Markdown
Collaborator

Overview

Add a dead-letter exchange and queue and put non-retryable messages there:

  • Adds DLX (dead-letter exchange) and DLQ (dead-letter queue) support in internal/queue/
  • Introduces ErrUnsupportedEvent sentinel error to distinguish non-retryable events
  • New ignoreMessage() function that Acks (vs Nacks) messages for unsupported events - these won't go to DLQ
  • discardMessage() uses Nack which routes to DLQ for retryable failures

Only messages that indicate data corruption or unexpected formats go to the DLQ for inspection. Valid messages that simply don't require processing are acknowledged and discarded.

Messages sent to DLQ (via Nack):

  • Malformed/corrupt messages that fail parsing (invalid JSON, invalid timestamps, missing required fields like workflow_job)

Messages NOT sent to DLQ (via Ack):

  • Non-workflow_job events (e.g., pull_request, push)
  • Unknown webhook actions (not queued/in_progress/completed/waiting)
  • waiting action (valid but not processed)
  • Non-self-hosted jobs

Rationale

Malformed/corrupt messages that fail parsing could indicate a serious issue (e.g. our code does not react to a format change of webhooks) and should be inspected.

Checklist

  • Changes comply with the project's coding standards and guidelines (see CONTRIBUTING.md and STYLE.md)
  • CONTRIBUTING.md has been updated upon changes to the contribution/development process (e.g. changes to the way tests are run)
  • Technical author has been assigned to review the PR in case of documentation changes (usually *.md files)

Minor technical update to CONTRIBUTING.md , no TA required.

cbartz and others added 23 commits January 5, 2026 14:34
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Implement DLQ mechanism for malformed webhook messages that should not
be retried (missing headers, invalid JSON, missing required fields).
Unsupported event types are now silently ignored via Ack instead of
being sent to DLQ.

- Add DeadLetterExchange and DeadLetterQueue to QueueConfig
- Create setupDeadLetterQueue() to encapsulate DLQ declaration
- Add declareQueueWithDeadLetter() with x-dead-letter-exchange arg
- Add ErrUnsupportedEvent sentinel error for ignorable events
- Add ignoreMessage() method that uses Ack for expected filtering
- Update pullMessage() to distinguish DLQ vs ignore paths

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
# Conflicts:
#	cmd/planner/main.go
#	cmd/planner/main_test.go
#	internal/planner/consumer.go
#	internal/queue/config.go
#	internal/queue/consumer.go
#	internal/queue/consumer_test.go
#	internal/queue/mock_test.go
#	internal/queue/types.go
@cbartz cbartz changed the title [WIP] feat: dead letter mechanism for non-retryable messages feat: dead letter mechanism for non-retryable messages Jan 8, 2026

@cbartz cbartz left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self-review

Comment thread .github/workflows/internal_tests.yaml
Comment thread cmd/planner/main_test.go
Comment thread cmd/planner/main_test.go
Comment thread cmd/planner/main_test.go
Comment thread internal/planner/consumer.go Outdated
Comment thread internal/planner/consumer.go
Comment thread internal/queue/types.go
@cbartz cbartz marked this pull request as ready for review January 8, 2026 07:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a dead letter mechanism for handling non-retryable messages in the webhook processing pipeline. Messages indicating data corruption or unexpected formats are routed to a Dead Letter Queue (DLQ) for inspection, while valid but unsupported events are acknowledged and discarded without DLQ routing.

  • Adds DLX (dead-letter exchange) and DLQ (dead-letter queue) infrastructure to the queue package
  • Introduces ErrUnsupportedEvent sentinel error to distinguish non-retryable from retryable failures
  • Separates message handling: ignoreMessage() uses Ack for valid unsupported events, discardMessage() uses Nack to route corrupt messages to DLQ

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated no comments.

Show a summary per file
File Description
internal/queue/types.go Updates error messages and adds declareQueueWithDeadLetter() function to support DLX configuration
internal/queue/mock_test.go Enhances mock channel to track DLX/DLQ declarations and queue arguments
internal/queue/deadletter_test.go Adds comprehensive tests for DLX/DLQ setup functionality
internal/queue/deadletter.go Implements setupDeadLetterQueue() to configure dead letter infrastructure
internal/queue/consumer_test.go Adds test verifying DLX/DLQ setup during consumer Pull operation
internal/queue/consumer.go Integrates DLX/DLQ setup into consumer initialization flow
internal/queue/config.go Adds DLX and DLQ configuration fields with default values
internal/planner/consumer_test.go Updates tests to reflect new message handling behavior (Ack vs Nack)
internal/planner/consumer.go Implements ErrUnsupportedEvent sentinel error and ignoreMessage() function; routes unsupported events appropriately
cmd/planner/main_test.go Refactors integration tests to verify DLQ behavior and adds scenario-based testing
CONTRIBUTING.md Updates Postgres version from 18.1 to 16.11 in Docker command
.github/workflows/planner_integration.yaml Updates Postgres service version from 18.1 to 16.11
.github/workflows/internal_tests.yaml Updates Postgres service version from 18.1 to 16.11

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@yanksyoon yanksyoon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nits + idempotency comment. Thanks!

Comment thread cmd/planner/main_test.go Outdated
Comment thread internal/planner/consumer.go Outdated
Comment thread internal/planner/consumer.go Outdated
Comment thread internal/queue/consumer.go Outdated
@cbartz cbartz requested review from yanksyoon and yhaliaw January 9, 2026 13:07
Comment thread internal/planner/consumer.go Outdated

@yanksyoon yanksyoon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for the changes 👍

@cbartz cbartz enabled auto-merge (squash) January 12, 2026 10:56
@cbartz cbartz merged commit 6ce37bd into main Jan 12, 2026
32 checks passed
@cbartz cbartz deleted the feat/dead-letter-ISD-4906 branch January 12, 2026 11:08
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.

4 participants