1/** 2 * TASK-0135 — the API→worker trace propagation helper (the spec's "job 3 * metadata carries the W3C traceparent — the dispatcher stores it, the 4 * processor resumes the span"). 5 * 6 * Carrier: BullMQ 5's `JobsOptions.telemetry.metadata` — the framework's own 7 * context-propagation field (persisted on the job as the `tm` Redis field and 8 * restored onto `job.opts.telemetry.metadata` when the worker fetches the 9 * job). We store the W3C traceparent string there. The app never configures a 10 * BullMQ `telemetry.meter`, so BullMQ's own (no-op) propagation hook leaves 11 * the field untouched — it is a pure carrier for us. 12 * 13 * Every BullMQ `Queue.add` in the API merges `jobTraceMetadata()` into the 14 * job options: 15 * 16 * await q.add("name", data, { ..., ...jobTraceMetadata() }); 17 * 18 * When there is no active span (OTel disabled, background context, unsampled) 19 * it returns `{}` — nothing is ever written. The worker's job-observability 20 * wrapper reads the same field (`job.opts.telemetry.metadata`) and resumes 21 * the span under it (one trace across api → queue → worker). 22 * 23 * Central (this one helper, not six copies) per AGENTS rule 5: the API has 24 * six enqueue sites; they all need the identical carrier shape. 25 */ 26import { captureTraceparent } from "@factory/observability"; 27 28export function jobTraceMetadata(): { telemetry?: { metadata: string } } { 29 const tp = captureTraceparent(); 30 return tp ? { telemetry: { metadata: tp } } : {}; 31} 32