whoa - so much - new features (UPC,etc) - Sentry for app logging! so much more !
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 1m10s
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 1m10s
This commit is contained in:
54
docs/adr/0051-asynchronous-context-propagation.md
Normal file
54
docs/adr/0051-asynchronous-context-propagation.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# ADR-051: Asynchronous Context Propagation
|
||||
|
||||
**Date**: 2026-01-11
|
||||
|
||||
**Status**: Accepted (Implemented)
|
||||
|
||||
## Context
|
||||
|
||||
Debugging asynchronous workflows is difficult because the `request_id` generated at the API layer is lost when a task is handed off to a background queue (BullMQ). Logs from the worker appear disconnected from the user action that triggered them.
|
||||
|
||||
## Decision
|
||||
|
||||
We will implement a context propagation pattern for all background jobs:
|
||||
|
||||
1. **Job Data Payload**: All job data interfaces MUST include a `meta` object containing `requestId`, `userId`, and `origin`.
|
||||
2. **Worker Logger Initialization**: All BullMQ workers MUST initialize a child logger immediately upon processing a job, using the metadata passed in the payload.
|
||||
3. **Correlation**: The worker's logger must use the _same_ `request_id` as the initiating API request.
|
||||
|
||||
## Implementation
|
||||
|
||||
```typescript
|
||||
// 1. Enqueueing (API Layer)
|
||||
await queue.add('process-flyer', {
|
||||
...data,
|
||||
meta: {
|
||||
requestId: req.log.bindings().request_id, // Propagate ID
|
||||
userId: req.user.id,
|
||||
},
|
||||
});
|
||||
|
||||
// 2. Processing (Worker Layer)
|
||||
const worker = new Worker('queue', async (job) => {
|
||||
const { requestId, userId } = job.data.meta || {};
|
||||
|
||||
// Create context-aware logger for this specific job execution
|
||||
const jobLogger = logger.child({
|
||||
request_id: requestId || uuidv4(), // Use propagated ID or generate new
|
||||
user_id: userId,
|
||||
job_id: job.id,
|
||||
service: 'worker',
|
||||
});
|
||||
|
||||
try {
|
||||
await processJob(job.data, jobLogger); // Pass logger down
|
||||
} catch (err) {
|
||||
jobLogger.error({ err }, 'Job failed');
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive**: Complete traceability from API request -> Queue -> Worker execution. Drastically reduces time to find "what happened" to a specific user request.
|
||||
Reference in New Issue
Block a user