Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 1m10s
1.7 KiB
1.7 KiB
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:
- Job Data Payload: All job data interfaces MUST include a
metaobject containingrequestId,userId, andorigin. - Worker Logger Initialization: All BullMQ workers MUST initialize a child logger immediately upon processing a job, using the metadata passed in the payload.
- Correlation: The worker's logger must use the same
request_idas the initiating API request.
Implementation
// 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.