@clipboard-health/mongo-jobs 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/package.json +41 -0
- package/src/index.d.ts +3 -0
- package/src/index.js +6 -0
- package/src/index.js.map +1 -0
- package/src/lib/backgroundJobs.d.ts +59 -0
- package/src/lib/backgroundJobs.js +108 -0
- package/src/lib/backgroundJobs.js.map +1 -0
- package/src/lib/handler.d.ts +6 -0
- package/src/lib/handler.js +3 -0
- package/src/lib/handler.js.map +1 -0
- package/src/lib/internal/cron.d.ts +29 -0
- package/src/lib/internal/cron.js +89 -0
- package/src/lib/internal/cron.js.map +1 -0
- package/src/lib/internal/duplicateRunningError.d.ts +2 -0
- package/src/lib/internal/duplicateRunningError.js +7 -0
- package/src/lib/internal/duplicateRunningError.js.map +1 -0
- package/src/lib/internal/handlerAlreadyRegisteredError.d.ts +2 -0
- package/src/lib/internal/handlerAlreadyRegisteredError.js +7 -0
- package/src/lib/internal/handlerAlreadyRegisteredError.js.map +1 -0
- package/src/lib/internal/jobsRepository.d.ts +51 -0
- package/src/lib/internal/jobsRepository.js +170 -0
- package/src/lib/internal/jobsRepository.js.map +1 -0
- package/src/lib/internal/logger.d.ts +4 -0
- package/src/lib/internal/logger.js +3 -0
- package/src/lib/internal/logger.js.map +1 -0
- package/src/lib/internal/metrics.d.ts +32 -0
- package/src/lib/internal/metrics.js +106 -0
- package/src/lib/internal/metrics.js.map +1 -0
- package/src/lib/internal/mongoDuplicate.d.ts +2 -0
- package/src/lib/internal/mongoDuplicate.js +9 -0
- package/src/lib/internal/mongoDuplicate.js.map +1 -0
- package/src/lib/internal/registry.d.ts +27 -0
- package/src/lib/internal/registry.js +78 -0
- package/src/lib/internal/registry.js.map +1 -0
- package/src/lib/internal/worker/actionableQueues.d.ts +7 -0
- package/src/lib/internal/worker/actionableQueues.js +32 -0
- package/src/lib/internal/worker/actionableQueues.js.map +1 -0
- package/src/lib/internal/worker/fairQueueConsumer.d.ts +24 -0
- package/src/lib/internal/worker/fairQueueConsumer.js +127 -0
- package/src/lib/internal/worker/fairQueueConsumer.js.map +1 -0
- package/src/lib/internal/worker/futureQueues.d.ts +5 -0
- package/src/lib/internal/worker/futureQueues.js +27 -0
- package/src/lib/internal/worker/futureQueues.js.map +1 -0
- package/src/lib/internal/worker/queueConsumer.d.ts +11 -0
- package/src/lib/internal/worker/queueConsumer.js +3 -0
- package/src/lib/internal/worker/queueConsumer.js.map +1 -0
- package/src/lib/internal/worker.d.ts +65 -0
- package/src/lib/internal/worker.js +342 -0
- package/src/lib/internal/worker.js.map +1 -0
- package/src/lib/job.d.ts +37 -0
- package/src/lib/job.js +29 -0
- package/src/lib/job.js.map +1 -0
- package/src/lib/schedule.d.ts +21 -0
- package/src/lib/schedule.js +16 -0
- package/src/lib/schedule.js.map +1 -0
- package/src/lib/testing.d.ts +9 -0
- package/src/lib/testing.js +37 -0
- package/src/lib/testing.js.map +1 -0
- package/src/lib/tracing.d.ts +8 -0
- package/src/lib/tracing.js +194 -0
- package/src/lib/tracing.js.map +1 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withProducerTrace = withProducerTrace;
|
|
4
|
+
exports.withConsumerTrace = withConsumerTrace;
|
|
5
|
+
exports.withInternalsTrace = withInternalsTrace;
|
|
6
|
+
const api_1 = require("@opentelemetry/api");
|
|
7
|
+
// According to the OpenTelemetry spec, the span name should follow the pattern of
|
|
8
|
+
// <destination name> <operation name>
|
|
9
|
+
// Where destination is the name of the queue and operation is the action being performed
|
|
10
|
+
//
|
|
11
|
+
// https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/messaging/#span-name
|
|
12
|
+
const TRACER_NAME = "mongo-jobs";
|
|
13
|
+
const PRODUCER_SPAN = "background-jobs.producer";
|
|
14
|
+
const CONSUMER_SPAN = "background-jobs.consumer";
|
|
15
|
+
const INTERNALS_SPAN = "background-jobs.internals";
|
|
16
|
+
const Component = {
|
|
17
|
+
BACKGROUND_JOBS: "background-jobs",
|
|
18
|
+
};
|
|
19
|
+
const Operation = {
|
|
20
|
+
PROCESS: "process",
|
|
21
|
+
PUBLISH: "publish",
|
|
22
|
+
};
|
|
23
|
+
const MessagingSystem = {
|
|
24
|
+
MONGO: "mongo-jobs",
|
|
25
|
+
};
|
|
26
|
+
const MessagingDestinationKind = {
|
|
27
|
+
QUEUE: "queue",
|
|
28
|
+
};
|
|
29
|
+
function resourceName(operation, destination) {
|
|
30
|
+
return `${operation} ${destination}`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Inject trace context into headers for propagation.
|
|
34
|
+
* This allows child spans to link back to the current parent span.
|
|
35
|
+
*/
|
|
36
|
+
function injectTraceHeaders() {
|
|
37
|
+
const traceHeaders = {};
|
|
38
|
+
api_1.propagation.inject(api_1.context.active(), traceHeaders);
|
|
39
|
+
return traceHeaders;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Extract trace context from headers to link spans.
|
|
43
|
+
* Returns a context with the parent span information.
|
|
44
|
+
*/
|
|
45
|
+
function extractTraceContext(traceHeaders) {
|
|
46
|
+
if (!traceHeaders) {
|
|
47
|
+
return api_1.context.active();
|
|
48
|
+
}
|
|
49
|
+
return api_1.propagation.extract(api_1.context.active(), traceHeaders);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create attributes for a producer telemetry span.
|
|
53
|
+
*
|
|
54
|
+
* Attributes definition for background jobs are still in RFC
|
|
55
|
+
* in the meantime, we should use the `messaging` convention
|
|
56
|
+
*
|
|
57
|
+
* Issue containing the RFC:
|
|
58
|
+
* - https://github.com/open-telemetry/opentelemetry-specification/pull/1582#issue-842434527
|
|
59
|
+
*
|
|
60
|
+
* Datadog supports the `messaging` convention:
|
|
61
|
+
* - https://docs.datadoghq.com/tracing/trace_collection/tracing_naming_convention#message-queue
|
|
62
|
+
*/
|
|
63
|
+
function producerAttributes(job) {
|
|
64
|
+
return {
|
|
65
|
+
component: Component.BACKGROUND_JOBS,
|
|
66
|
+
"messaging.system": MessagingSystem.MONGO,
|
|
67
|
+
"messaging.operation": Operation.PUBLISH,
|
|
68
|
+
"messaging.destination": job.handlerName,
|
|
69
|
+
"messaging.destination_kind": MessagingDestinationKind.QUEUE,
|
|
70
|
+
"messaging.mongo-bg-jobs.queue": job.queue ?? "unknown",
|
|
71
|
+
"resource.name": resourceName(Operation.PUBLISH, job.handlerName),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function consumerAttributes(job) {
|
|
75
|
+
return {
|
|
76
|
+
component: Component.BACKGROUND_JOBS,
|
|
77
|
+
"span.type": "worker",
|
|
78
|
+
"messaging.system": MessagingSystem.MONGO,
|
|
79
|
+
"messaging.operation": Operation.PROCESS,
|
|
80
|
+
"messaging.message_id": job._id.toString(),
|
|
81
|
+
"messaging.destination": job.handlerName,
|
|
82
|
+
"messaging.destination_kind": MessagingDestinationKind.QUEUE,
|
|
83
|
+
"messaging.mongo-bg-jobs.queue": job.queue ?? "unknown",
|
|
84
|
+
"messaging.mongo-bg-jobs.attemptsCount": job.attemptsCount.toString(),
|
|
85
|
+
"messaging.mongo-bg-jobs.createdAt": job.createdAt.toISOString(),
|
|
86
|
+
"messaging.mongo-bg-jobs.updatedAt": job.updatedAt.toISOString(),
|
|
87
|
+
"messaging.mongo-bg-jobs.nextRunAt": job.nextRunAt?.toISOString() ?? "",
|
|
88
|
+
"messaging.mongo-bg-jobs.lockedAt": job.lockedAt?.toISOString() ?? "",
|
|
89
|
+
"messaging.mongo-bg-jobs.failedAt": job.failedAt?.toISOString() ?? "",
|
|
90
|
+
"resource.name": resourceName(Operation.PROCESS, job.handlerName),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function isCronJob(job) {
|
|
94
|
+
return job.scheduleName !== undefined;
|
|
95
|
+
}
|
|
96
|
+
async function withProducerTrace(handler, data, callback) {
|
|
97
|
+
const tracer = api_1.trace.getTracer(TRACER_NAME);
|
|
98
|
+
const handlerName = handler.name;
|
|
99
|
+
return await tracer.startActiveSpan(PRODUCER_SPAN, {
|
|
100
|
+
kind: api_1.SpanKind.PRODUCER,
|
|
101
|
+
attributes: {
|
|
102
|
+
"resource.name": resourceName(Operation.PUBLISH, handlerName),
|
|
103
|
+
},
|
|
104
|
+
}, async (span) => {
|
|
105
|
+
try {
|
|
106
|
+
// Inject trace context for distributed tracing
|
|
107
|
+
const traceHeaders = injectTraceHeaders();
|
|
108
|
+
const job = await callback({ ...data, _traceHeaders: traceHeaders });
|
|
109
|
+
if (job) {
|
|
110
|
+
span.setAttributes(producerAttributes(job));
|
|
111
|
+
}
|
|
112
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
113
|
+
return job;
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
span.setStatus({
|
|
117
|
+
code: api_1.SpanStatusCode.ERROR,
|
|
118
|
+
message: error instanceof Error ? error.message : String(error),
|
|
119
|
+
});
|
|
120
|
+
span.recordException(error);
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
span.end();
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async function executeJobTrace(tracer, attributes, parentContext, callback) {
|
|
129
|
+
await tracer.startActiveSpan(CONSUMER_SPAN, {
|
|
130
|
+
kind: api_1.SpanKind.CONSUMER,
|
|
131
|
+
attributes,
|
|
132
|
+
}, parentContext, async (span) => {
|
|
133
|
+
try {
|
|
134
|
+
await callback();
|
|
135
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
span.setStatus({
|
|
139
|
+
code: api_1.SpanStatusCode.ERROR,
|
|
140
|
+
message: error instanceof Error ? error.message : String(error),
|
|
141
|
+
});
|
|
142
|
+
span.recordException(error);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
span.end();
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
async function withConsumerTrace(job, callback) {
|
|
151
|
+
const tracer = api_1.trace.getTracer(TRACER_NAME);
|
|
152
|
+
const attributes = consumerAttributes(job);
|
|
153
|
+
let parentContext;
|
|
154
|
+
if (isCronJob(job)) {
|
|
155
|
+
/**
|
|
156
|
+
* We need to manually remove the context of traces for cron jobs.
|
|
157
|
+
* Otherwise cron jobs traces are shown in the context of the entire worker and they
|
|
158
|
+
* are not very pleasant to look at in Datadog (sometimes impossible).
|
|
159
|
+
**/
|
|
160
|
+
parentContext = api_1.ROOT_CONTEXT;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const jobData = job.data || {};
|
|
164
|
+
parentContext = extractTraceContext(jobData._traceHeaders);
|
|
165
|
+
}
|
|
166
|
+
await executeJobTrace(tracer, attributes, parentContext, callback);
|
|
167
|
+
}
|
|
168
|
+
async function withInternalsTrace(resource, callback) {
|
|
169
|
+
const tracer = api_1.trace.getTracer(TRACER_NAME);
|
|
170
|
+
return await tracer.startActiveSpan(INTERNALS_SPAN, {
|
|
171
|
+
kind: api_1.SpanKind.INTERNAL,
|
|
172
|
+
attributes: {
|
|
173
|
+
"resource.name": resource,
|
|
174
|
+
},
|
|
175
|
+
}, async (span) => {
|
|
176
|
+
try {
|
|
177
|
+
const result = await callback();
|
|
178
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
span.setStatus({
|
|
183
|
+
code: api_1.SpanStatusCode.ERROR,
|
|
184
|
+
message: error instanceof Error ? error.message : String(error),
|
|
185
|
+
});
|
|
186
|
+
span.recordException(error);
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
span.end();
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=tracing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../../../../packages/mongo-jobs/src/lib/tracing.ts"],"names":[],"mappings":"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"}
|