Skip to content

About

Doing architecture with Nestjs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

BullMQ + NestJS — API Routes

Prerequisites

  • Node.js
  • Redis running locally on port 6379
  • SHIPPING_PROVIDER_URL env var set (defaults to http://localhost:8000/api/update-order-status), used by the send-to-shipping-provider job
  • SHIPPING_PROVIDER_SIMULATE_FAILURE=true to deterministically force every send-to-shipping-provider attempt to fail (no network call made) — handy for demoing the DLQ without needing to actually take a service down. Defaults to false/unset.
  • DLQ_ALERT_THRESHOLD (optional, default 1) — DLQ depth (waiting count) at which a log-level alert is emitted
docker run -p 6379:6379 redis
npm install
npm run start:dev

Base URL: http://localhost:3000


Routes

GET /

Health check / welcome message.

curl http://localhost:3000/

GET /user/register

Registers a user. Emits UserRegisteredEvent → enqueues a send-registration-email job.

Query param Type Required Description
email string yes User's email address
curl "http://localhost:3000/user/register?email=someone@example.com"

Response

{ "message": "Registration event emitted for someone@example.com" }

GET /user/forgot-password

Requests a password reset. Emits PasswordResetRequestedEvent → enqueues a send-password-reset-email job.

Query param Type Required Description
email string yes User's email address
curl "http://localhost:3000/user/forgot-password?email=someone@example.com"

Response

{ "message": "Password reset event emitted for someone@example.com" }

GET /order/place

Places an order. Emits OrderPlacedEvent → fans out to two jobs: send-to-shipping-provider and send-confirmation-email.

Query param Type Required Description
orderId string yes Order ID
email string yes Customer email
curl "http://localhost:3000/order/place?orderId=123&email=someone@example.com"

Response

{ "message": "Order placed event emitted for order 123" }

GET /order/dlq

Lists current entries in the order-dlq dead-letter queue (jobs that exhausted all send-to-shipping-provider retry attempts). Each entry includes the original job name/queue, payload, failedReason, stack trace, attempts made, first-attempt/final-failure timestamps, the originating request ID, and how many times it's already been reprocessed.

curl http://localhost:3000/order/dlq

POST /order/dlq/:id/reprocess

Reconstructs the original job payload from a DLQ entry and re-adds it to the order queue, then removes the DLQ entry. :id is the DLQ job's own ID (as returned by GET /order/dlq), not the original order job's ID.

curl -X POST http://localhost:3000/order/dlq/12/reprocess

Poison-pill guard: each reprocess attempt increments a reprocessCount carried in the job's options metadata, so the count survives a fail → reprocess → fail cycle. After 3 reprocess attempts, further reprocessing is refused (400 Bad Request) until someone investigates manually — reprocessing is manual-only, there is no auto-retry out of the DLQ.


Dead Letter Queue (DLQ)

When a send-to-shipping-provider job exhausts all configured attempts (checked via job.attemptsMade >= job.opts.attempts in OrderProcessor's @OnWorkerEvent('failed') handler, so only truly exhausted jobs are captured — not every individual retry), it's moved into the order-dlq queue instead of being left in BullMQ's default failed state. The original job is removed from order once it's copied over, so the DLQ is the single place to look for exhausted jobs.

  • Demo trigger: set SHIPPING_PROVIDER_SIMULATE_FAILURE=true to force failures deterministically.
  • Inspection: order-dlq is registered in Bull Board alongside order/user, and GET /order/dlq gives a readable JSON view.
  • Reprocessing: POST /order/dlq/:id/reprocess, capped at 3 attempts per entry (see above).

Bull Board

Inspect queues and job status at:

http://localhost:3000/admin/queues

This includes the order-dlq queue.

About

Doing architecture with Nestjs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages