Description
The outbox delivered by #122 has a complete producer side — transactional writes, typed status, leasing, backoff, dead-letter, and versioned payload validation — but only one consumer. src/workers/wallet-provisioning.worker.ts is bound directly to WalletProvisioningOutboxHandler, so it drains only wallet provisioning work. event-schema.ts already registers UserCreated alongside the wallet events, and nothing consumes it: those rows are written inside the request transaction and then stay PENDING forever. Every new domain event today needs its own bespoke worker process.
Add a single relay that leases any pending outbox event and dispatches it by eventType to registered handlers, so domains subscribe to events instead of shipping a worker each.
File Location
learnault-api/src/lib/transactions/, learnault-api/src/jobs/, learnault-api/src/workers/, and learnault-api/docs/domains/REQUEST_AND_EVENT_FLOWS.md
Design Reference
API Roadmap Phase 1.1: Add Outbox Event Relay and Handler Registry. Consumes the primitives delivered by #122.
Dependencies
Tasks
Acceptance Criteria
- A new domain event needs a registered handler, not a new worker process
UserCreated events are consumed and no longer accumulate in PENDING
- An event with no registered handler fails loudly at startup rather than silently stalling
- A failing handler retries with backoff and dead-letters without blocking other event types
- Replayed dead-letter events produce no duplicate side effects
Verification Evidence
Difficulty
Advanced
Description
The outbox delivered by #122 has a complete producer side — transactional writes, typed status, leasing, backoff, dead-letter, and versioned payload validation — but only one consumer.
src/workers/wallet-provisioning.worker.tsis bound directly toWalletProvisioningOutboxHandler, so it drains only wallet provisioning work.event-schema.tsalready registersUserCreatedalongside the wallet events, and nothing consumes it: those rows are written inside the request transaction and then stayPENDINGforever. Every new domain event today needs its own bespoke worker process.Add a single relay that leases any pending outbox event and dispatches it by
eventTypeto registered handlers, so domains subscribe to events instead of shipping a worker each.File Location
learnault-api/src/lib/transactions/,learnault-api/src/jobs/,learnault-api/src/workers/, andlearnault-api/docs/domains/REQUEST_AND_EVENT_FLOWS.mdDesign Reference
API Roadmap Phase 1.1: Add Outbox Event Relay and Handler Registry. Consumes the primitives delivered by #122.
Dependencies
Tasks
eventTypeandeventVersionJobAttemptUserCreatedhandler so the already-emitted event stops accumulating unconsumedPUBLISHEDonly when every registered handler for that type succeedsAcceptance Criteria
UserCreatedevents are consumed and no longer accumulate inPENDINGVerification Evidence
Difficulty
Advanced