Description
The webhook_outbox table in PostgreSQL is populated when stream events occur, but the dispatcher that reads the outbox and performs actual HTTP delivery to consumer endpoints is not fully implemented in src/webhooks/service.ts. Rows accumulate in webhook_outbox indefinitely without being delivered. A polling dispatcher with at-least-once delivery semantics must be built and wired into the service startup lifecycle.
Requirements and context
- Implement a
WebhookDispatcher class in src/webhooks/service.ts that polls webhook_outbox for unprocessed rows on a configurable WEBHOOK_POLL_INTERVAL_MS
- Use
SELECT ... FOR UPDATE SKIP LOCKED to safely claim rows across concurrent workers without double-delivery
- Mark rows as processed by setting
processed flag and delegating retries to src/webhooks/retry.ts on delivery failure
- Must be secure, tested, and documented
- Should be efficient and easy to review
Suggested execution
Fork the repo and create a branch
git checkout -b feature/webhook-outbox-dispatcher
Implement changes
- Update/Write:
src/webhooks/service.ts — WebhookDispatcher with polling loop and FOR UPDATE SKIP LOCKED
- Update/Write:
src/webhooks/retry.ts — integrate dispatcher failure path with retry scheduling
- Update/Write:
src/shutdown.ts — gracefully drain in-flight deliveries on SIGTERM
- Write comprehensive tests:
tests/webhooks/service.dispatcher.test.ts
- Add documentation:
docs/webhooks.md — document outbox dispatcher lifecycle and delivery guarantees
- Include clear code comments and types
- Validate security assumptions
Test and commit
- Run tests:
pnpm test (or pnpm test:coverage)
- Cover edge cases: empty outbox (no-op), successful delivery marks row processed, failed delivery enqueues retry, concurrent workers skip locked rows, graceful shutdown drains in-flight batch
- Include test output and security notes
Example commit message
feat: implement live webhook outbox dispatcher with at-least-once delivery
Guidelines
- Minimum 95 percent test coverage
- Clear documentation
- Timeframe: 96 hours
Description
The
webhook_outboxtable in PostgreSQL is populated when stream events occur, but the dispatcher that reads the outbox and performs actual HTTP delivery to consumer endpoints is not fully implemented insrc/webhooks/service.ts. Rows accumulate inwebhook_outboxindefinitely without being delivered. A polling dispatcher with at-least-once delivery semantics must be built and wired into the service startup lifecycle.Requirements and context
WebhookDispatcherclass insrc/webhooks/service.tsthat pollswebhook_outboxfor unprocessed rows on a configurableWEBHOOK_POLL_INTERVAL_MSSELECT ... FOR UPDATE SKIP LOCKEDto safely claim rows across concurrent workers without double-deliveryprocessedflag and delegating retries tosrc/webhooks/retry.tson delivery failureSuggested execution
Fork the repo and create a branch
Implement changes
src/webhooks/service.ts—WebhookDispatcherwith polling loop andFOR UPDATE SKIP LOCKEDsrc/webhooks/retry.ts— integrate dispatcher failure path with retry schedulingsrc/shutdown.ts— gracefully drain in-flight deliveries on SIGTERMtests/webhooks/service.dispatcher.test.tsdocs/webhooks.md— document outbox dispatcher lifecycle and delivery guaranteesTest and commit
pnpm test(orpnpm test:coverage)Example commit message
Guidelines