@lavoro/core 0.3.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/build/index.d.ts +595 -0
- package/build/index.js +984 -0
- package/build/index.js.map +1 -0
- package/package.json +54 -0
package/build/index.js
ADDED
|
@@ -0,0 +1,984 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __reflectGet = Reflect.get;
|
|
9
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __spreadValues = (a, b) => {
|
|
11
|
+
for (var prop in b || (b = {}))
|
|
12
|
+
if (__hasOwnProp.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
if (__getOwnPropSymbols)
|
|
15
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
16
|
+
if (__propIsEnum.call(b, prop))
|
|
17
|
+
__defNormalProp(a, prop, b[prop]);
|
|
18
|
+
}
|
|
19
|
+
return a;
|
|
20
|
+
};
|
|
21
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
22
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
23
|
+
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
|
|
24
|
+
var __async = (__this, __arguments, generator) => {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
var fulfilled = (value) => {
|
|
27
|
+
try {
|
|
28
|
+
step(generator.next(value));
|
|
29
|
+
} catch (e) {
|
|
30
|
+
reject(e);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var rejected = (value) => {
|
|
34
|
+
try {
|
|
35
|
+
step(generator.throw(value));
|
|
36
|
+
} catch (e) {
|
|
37
|
+
reject(e);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
41
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// src/logger.ts
|
|
46
|
+
import pino from "pino";
|
|
47
|
+
var Logger = class _Logger {
|
|
48
|
+
constructor(internalLogger) {
|
|
49
|
+
__publicField(this, "internalLogger");
|
|
50
|
+
this.internalLogger = internalLogger;
|
|
51
|
+
}
|
|
52
|
+
child(obj) {
|
|
53
|
+
return new _Logger(this.internalLogger.child(obj));
|
|
54
|
+
}
|
|
55
|
+
trace(msg, obj) {
|
|
56
|
+
this.internalLogger.trace(msg, obj);
|
|
57
|
+
}
|
|
58
|
+
debug(msg, obj) {
|
|
59
|
+
this.internalLogger.debug(msg, obj);
|
|
60
|
+
}
|
|
61
|
+
warn(msg, obj) {
|
|
62
|
+
this.internalLogger.warn(msg, obj);
|
|
63
|
+
}
|
|
64
|
+
error(msg, obj) {
|
|
65
|
+
this.internalLogger.error(msg, obj);
|
|
66
|
+
}
|
|
67
|
+
fatal(msg, obj) {
|
|
68
|
+
this.internalLogger.fatal(msg, obj);
|
|
69
|
+
}
|
|
70
|
+
info(msg, obj) {
|
|
71
|
+
this.internalLogger.info(msg, obj);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
function createDefaultLogger(name, level = "info") {
|
|
75
|
+
return new Logger(pino({ name, level }));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/queue/define_config.ts
|
|
79
|
+
import { RuntimeException } from "@poppinss/utils";
|
|
80
|
+
function defineConfig(config) {
|
|
81
|
+
if (!config.connection) {
|
|
82
|
+
throw new RuntimeException(
|
|
83
|
+
'Missing "connection" property in queue config file'
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (!config.connections) {
|
|
87
|
+
throw new RuntimeException(
|
|
88
|
+
'Missing "connections" property in queue config file'
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (!config.connections[config.connection]) {
|
|
92
|
+
throw new RuntimeException(
|
|
93
|
+
`Missing "connections.${String(config.connection)}". It is referenced by the "connection" property`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
Object.keys(config.connections).forEach((connectionName) => {
|
|
97
|
+
const connection = config.connections[connectionName];
|
|
98
|
+
if (!connection.queues || Object.keys(connection.queues).length === 0) {
|
|
99
|
+
throw new RuntimeException(
|
|
100
|
+
`Connection "${connectionName}" must have at least one queue defined`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
return config;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/queue/pending_dispatch.ts
|
|
108
|
+
var PendingDispatch = class {
|
|
109
|
+
constructor(job, payload) {
|
|
110
|
+
this.job = job;
|
|
111
|
+
this.payload = payload;
|
|
112
|
+
}
|
|
113
|
+
onConnection(connection) {
|
|
114
|
+
this.job.options.connection = connection;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
onQueue(queue) {
|
|
118
|
+
this.job.options.queue = queue;
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
// public withQueueServiceResolver(
|
|
122
|
+
// queueServiceResolver: () => Promise<Queue>,
|
|
123
|
+
// ): this {
|
|
124
|
+
// this.job.setQueueServiceResolver(queueServiceResolver)
|
|
125
|
+
// return this
|
|
126
|
+
// }
|
|
127
|
+
execute() {
|
|
128
|
+
return __async(this, null, function* () {
|
|
129
|
+
if (!this.job.getQueueServiceResolver) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
"Queue service resolver is not set.\nDid you forget to call Job.setDefaultQueueServiceResolver()?"
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
const queue = yield this.job.getQueueServiceResolver();
|
|
135
|
+
yield queue.enqueue(this.job, this.payload);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* By defining the "then" method, PendingDispatch becomes "thenable",
|
|
140
|
+
* allowing it to trigger automatically when await is called.
|
|
141
|
+
*/
|
|
142
|
+
then(onfulfilled, onrejected) {
|
|
143
|
+
return __async(this, null, function* () {
|
|
144
|
+
return this.execute().then(onfulfilled, onrejected);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// src/queue/contracts/job.ts
|
|
150
|
+
import { randomUUID } from "crypto";
|
|
151
|
+
var _Job = class _Job {
|
|
152
|
+
constructor() {
|
|
153
|
+
__publicField(this, "_id", randomUUID());
|
|
154
|
+
__publicField(this, "options", {
|
|
155
|
+
retries: 3,
|
|
156
|
+
delay: 0
|
|
157
|
+
});
|
|
158
|
+
__publicField(this, "queueServiceResolver");
|
|
159
|
+
}
|
|
160
|
+
static compileName(queue, name) {
|
|
161
|
+
return `${queue}_${name}`;
|
|
162
|
+
}
|
|
163
|
+
static parseName(name) {
|
|
164
|
+
const [q, n] = name.split(/_(.+)/);
|
|
165
|
+
return { queue: q, name: n };
|
|
166
|
+
}
|
|
167
|
+
get connection() {
|
|
168
|
+
return this.options.connection;
|
|
169
|
+
}
|
|
170
|
+
set connection(connection) {
|
|
171
|
+
this.options.connection = connection;
|
|
172
|
+
}
|
|
173
|
+
get queue() {
|
|
174
|
+
return this.options.queue;
|
|
175
|
+
}
|
|
176
|
+
set queue(queue) {
|
|
177
|
+
this.options.queue = queue;
|
|
178
|
+
}
|
|
179
|
+
get name() {
|
|
180
|
+
return this.constructor.name;
|
|
181
|
+
}
|
|
182
|
+
get id() {
|
|
183
|
+
return this._id;
|
|
184
|
+
}
|
|
185
|
+
set id(id) {
|
|
186
|
+
this._id = id;
|
|
187
|
+
}
|
|
188
|
+
get fullyQualifiedName() {
|
|
189
|
+
if (!this.options.queue) {
|
|
190
|
+
throw new Error("Queue is not set.");
|
|
191
|
+
}
|
|
192
|
+
return _Job.compileName(this.options.queue, this.name);
|
|
193
|
+
}
|
|
194
|
+
static setDefaultQueueServiceResolver(queueServiceResolver) {
|
|
195
|
+
this.defaultQueueServiceResolver = queueServiceResolver;
|
|
196
|
+
}
|
|
197
|
+
setQueueServiceResolver(queueServiceResolver) {
|
|
198
|
+
this.queueServiceResolver = queueServiceResolver;
|
|
199
|
+
}
|
|
200
|
+
get getQueueServiceResolver() {
|
|
201
|
+
return this.queueServiceResolver || _Job.defaultQueueServiceResolver;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Dispatch a job of type with a typed payload.
|
|
205
|
+
*/
|
|
206
|
+
static dispatch(payload) {
|
|
207
|
+
const job = new this();
|
|
208
|
+
return new PendingDispatch(job, payload);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
__publicField(_Job, "defaultQueueServiceResolver");
|
|
212
|
+
var Job = _Job;
|
|
213
|
+
|
|
214
|
+
// src/queue/contracts/queue_driver.ts
|
|
215
|
+
var QueueDriver = class {
|
|
216
|
+
constructor(config, options, driverConfig = {}) {
|
|
217
|
+
this.config = config;
|
|
218
|
+
this.options = options;
|
|
219
|
+
this.driverConfig = driverConfig;
|
|
220
|
+
__publicField(this, "logger");
|
|
221
|
+
__publicField(this, "registeredQueues", /* @__PURE__ */ new Set());
|
|
222
|
+
__publicField(this, "registeredJobs", /* @__PURE__ */ new Map());
|
|
223
|
+
__publicField(this, "connection");
|
|
224
|
+
this.logger = createDefaultLogger("queue");
|
|
225
|
+
}
|
|
226
|
+
setLogger(logger) {
|
|
227
|
+
this.logger = logger;
|
|
228
|
+
}
|
|
229
|
+
getMergedWorkerOptions(queue, options) {
|
|
230
|
+
const base = this.options[queue] || {};
|
|
231
|
+
return __spreadValues(__spreadValues({}, base), options || {});
|
|
232
|
+
}
|
|
233
|
+
listen(queue, options) {
|
|
234
|
+
return __async(this, null, function* () {
|
|
235
|
+
if (this.registeredQueues.has(queue)) {
|
|
236
|
+
throw new Error(`Queue '${queue}' already registered`);
|
|
237
|
+
}
|
|
238
|
+
this.registeredQueues.add(queue);
|
|
239
|
+
const workerOptions = this.getMergedWorkerOptions(queue, options);
|
|
240
|
+
this.logger.trace(
|
|
241
|
+
{ connection: this.connection, queue, options: workerOptions },
|
|
242
|
+
"Listening queue"
|
|
243
|
+
);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
register(job) {
|
|
247
|
+
return __async(this, null, function* () {
|
|
248
|
+
if (this.registeredJobs.has(job.name)) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
this.registeredJobs.set(job.name, job);
|
|
252
|
+
this.logger.trace(
|
|
253
|
+
{ connection: this.connection, job: job.name },
|
|
254
|
+
"Registered job"
|
|
255
|
+
);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
unregister(job) {
|
|
259
|
+
return __async(this, null, function* () {
|
|
260
|
+
if (!this.registeredJobs.has(job.name)) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
this.registeredJobs.delete(job.name);
|
|
264
|
+
this.logger.trace(
|
|
265
|
+
{ connection: this.connection, job: job.name },
|
|
266
|
+
"Unregistered job"
|
|
267
|
+
);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
start() {
|
|
271
|
+
return __async(this, null, function* () {
|
|
272
|
+
for (const [queue, options] of Object.entries(this.options)) {
|
|
273
|
+
yield this.listen(queue, options);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
stop(_options) {
|
|
278
|
+
return __async(this, null, function* () {
|
|
279
|
+
this.registeredQueues.clear();
|
|
280
|
+
this.registeredJobs.clear();
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
checkIfQueueIsRegistered(queue) {
|
|
284
|
+
if (!this.registeredQueues.has(queue)) {
|
|
285
|
+
throw new Error(`Queue '${queue}' is not registered.`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
checkIfJobIsRegistered(job) {
|
|
289
|
+
if (!this.registeredJobs.has(job)) {
|
|
290
|
+
throw new Error(`Job '${job}' is not registered.`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
getDefaultQueue() {
|
|
294
|
+
if (this.registeredQueues.size === 0) {
|
|
295
|
+
throw new Error(
|
|
296
|
+
`No queues registered for connection: ${this.connection}.`
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
return this.registeredQueues.values().next().value;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Parent method to be extended by the driver.
|
|
303
|
+
* It implements checks for the job and queue being registered.
|
|
304
|
+
*/
|
|
305
|
+
enqueue(job, payload) {
|
|
306
|
+
return __async(this, null, function* () {
|
|
307
|
+
if (!job.options.queue) {
|
|
308
|
+
job.options.queue = this.getDefaultQueue();
|
|
309
|
+
}
|
|
310
|
+
this.checkIfQueueIsRegistered(job.options.queue);
|
|
311
|
+
this.checkIfJobIsRegistered(job.name);
|
|
312
|
+
return Promise.resolve();
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Clean up resources associated with a lock factory created by this driver.
|
|
317
|
+
* This is called when the queue is stopped to ensure proper resource cleanup.
|
|
318
|
+
*
|
|
319
|
+
* @param lockFactory - The lock factory instance to clean up
|
|
320
|
+
*/
|
|
321
|
+
destroyLockProvider(_lockFactory) {
|
|
322
|
+
return __async(this, null, function* () {
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
// src/schedule/schedule_interval.ts
|
|
328
|
+
function parseTime(time) {
|
|
329
|
+
const [hour, minute] = time.split(":");
|
|
330
|
+
if (!hour || !minute || hour.length !== 2 || minute.length !== 2) {
|
|
331
|
+
throw new Error("Invalid time format");
|
|
332
|
+
}
|
|
333
|
+
return [Number(hour), Number(minute)];
|
|
334
|
+
}
|
|
335
|
+
function dayOfWeekToNumber(dayOfWeek) {
|
|
336
|
+
switch (dayOfWeek) {
|
|
337
|
+
case "sunday":
|
|
338
|
+
return 0;
|
|
339
|
+
case "monday":
|
|
340
|
+
return 1;
|
|
341
|
+
case "tuesday":
|
|
342
|
+
return 2;
|
|
343
|
+
case "wednesday":
|
|
344
|
+
return 3;
|
|
345
|
+
case "thursday":
|
|
346
|
+
return 4;
|
|
347
|
+
case "friday":
|
|
348
|
+
return 5;
|
|
349
|
+
case "saturday":
|
|
350
|
+
return 6;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function intervalToCron(interval, options = {}) {
|
|
354
|
+
const { minute = 0, hour = 0, dayOfMonth = 1, dayOfWeek } = options;
|
|
355
|
+
const dayOfWeekNumber = dayOfWeekToNumber(dayOfWeek != null ? dayOfWeek : "sunday");
|
|
356
|
+
const patterns = {
|
|
357
|
+
second: "* * * * * *",
|
|
358
|
+
"two seconds": "*/2 * * * * *",
|
|
359
|
+
"three seconds": "*/3 * * * * *",
|
|
360
|
+
"four seconds": "*/4 * * * * *",
|
|
361
|
+
"five seconds": "*/5 * * * * *",
|
|
362
|
+
"ten seconds": "*/10 * * * * *",
|
|
363
|
+
"fifteen seconds": "*/15 * * * * *",
|
|
364
|
+
"twenty seconds": "*/20 * * * * *",
|
|
365
|
+
"thirty seconds": "*/30 * * * * *",
|
|
366
|
+
minute: "* * * * *",
|
|
367
|
+
"two minutes": "*/2 * * * *",
|
|
368
|
+
"three minutes": "*/3 * * * *",
|
|
369
|
+
"four minutes": "*/4 * * * *",
|
|
370
|
+
"five minutes": "*/5 * * * *",
|
|
371
|
+
"ten minutes": "*/10 * * * *",
|
|
372
|
+
"fifteen minutes": "*/15 * * * *",
|
|
373
|
+
"twenty minutes": "*/20 * * * *",
|
|
374
|
+
"thirty minutes": "*/30 * * * *",
|
|
375
|
+
hour: `${minute} * * * *`,
|
|
376
|
+
"two hours": `${minute} */2 * * *`,
|
|
377
|
+
"three hours": `${minute} */3 * * *`,
|
|
378
|
+
"four hours": `${minute} */4 * * *`,
|
|
379
|
+
"five hours": `${minute} */5 * * *`,
|
|
380
|
+
"six hours": `${minute} */6 * * *`,
|
|
381
|
+
"seven hours": `${minute} */7 * * *`,
|
|
382
|
+
"eight hours": `${minute} */8 * * *`,
|
|
383
|
+
"nine hours": `${minute} */9 * * *`,
|
|
384
|
+
"ten hours": `${minute} */10 * * *`,
|
|
385
|
+
"eleven hours": `${minute} */11 * * *`,
|
|
386
|
+
"twelve hours": `${minute} */12 * * *`,
|
|
387
|
+
day: `${minute} ${hour} * * *`,
|
|
388
|
+
week: `${minute} ${hour} * * ${dayOfWeekNumber}`,
|
|
389
|
+
sunday: `${minute} ${hour} * * 0`,
|
|
390
|
+
monday: `${minute} ${hour} * * 1`,
|
|
391
|
+
tuesday: `${minute} ${hour} * * 2`,
|
|
392
|
+
wednesday: `${minute} ${hour} * * 3`,
|
|
393
|
+
thursday: `${minute} ${hour} * * 4`,
|
|
394
|
+
friday: `${minute} ${hour} * * 5`,
|
|
395
|
+
saturday: `${minute} ${hour} * * 6`,
|
|
396
|
+
month: `${minute} ${hour} ${dayOfWeek ? "*" : dayOfMonth} * ${dayOfWeek ? dayOfWeekNumber + "#1" : "*"}`,
|
|
397
|
+
"last day of month": `${minute} ${hour} L * *`
|
|
398
|
+
// quarter: `${minute} ${hour} ${dayOfWeek ? '*' : dayOfMonth} */3 ${dayOfWeek ? dayOfWeekNumber : '*'}`,
|
|
399
|
+
// year: `${minute} ${hour} ${dayOfMonth} 1 ${dayOfWeek ? dayOfWeekNumber : '*'}`,
|
|
400
|
+
};
|
|
401
|
+
return patterns[interval];
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// src/schedule/schedule_registry.ts
|
|
405
|
+
var ScheduleRegistry = class {
|
|
406
|
+
static add(name, cron) {
|
|
407
|
+
if (this.instances[name]) {
|
|
408
|
+
throw new Error(`Cron instance with name '${name}' already exists`);
|
|
409
|
+
}
|
|
410
|
+
this.instances[name] = cron;
|
|
411
|
+
}
|
|
412
|
+
static all() {
|
|
413
|
+
return this.instances;
|
|
414
|
+
}
|
|
415
|
+
static get(name) {
|
|
416
|
+
return this.instances[name];
|
|
417
|
+
}
|
|
418
|
+
static clear(name) {
|
|
419
|
+
var _a;
|
|
420
|
+
if (name) {
|
|
421
|
+
(_a = this.instances[name]) == null ? void 0 : _a.stop();
|
|
422
|
+
delete this.instances[name];
|
|
423
|
+
} else {
|
|
424
|
+
Object.values(this.instances).forEach((cron) => cron.stop());
|
|
425
|
+
this.instances = {};
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
__publicField(ScheduleRegistry, "instances", {});
|
|
430
|
+
|
|
431
|
+
// src/schedule/pending_schedule.ts
|
|
432
|
+
import { Cron } from "croner";
|
|
433
|
+
import { createHash } from "crypto";
|
|
434
|
+
var getDistributedLockKey = (name) => {
|
|
435
|
+
const hash = createHash("sha1").update(name).digest("hex").slice(0, 8);
|
|
436
|
+
return `lavoro:schedule:${hash}`;
|
|
437
|
+
};
|
|
438
|
+
var PendingSchedule = class {
|
|
439
|
+
constructor(name, cb, lockProviderResolver) {
|
|
440
|
+
this.name = name;
|
|
441
|
+
this.cb = cb;
|
|
442
|
+
this.lockProviderResolver = lockProviderResolver;
|
|
443
|
+
__publicField(this, "cronPattern");
|
|
444
|
+
__publicField(this, "interval", "day");
|
|
445
|
+
__publicField(this, "intervalOptions");
|
|
446
|
+
__publicField(this, "distributedLockOptions", {
|
|
447
|
+
key: getDistributedLockKey,
|
|
448
|
+
ttl: "1m",
|
|
449
|
+
// TODO: Decide on a default TTL
|
|
450
|
+
overlap: false,
|
|
451
|
+
handOff: false
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Schedule using a cron pattern.
|
|
456
|
+
* You can use https://crontab.guru to generate a cron pattern.
|
|
457
|
+
*
|
|
458
|
+
* @param pattern - Cron pattern string
|
|
459
|
+
*
|
|
460
|
+
* @example
|
|
461
|
+
* Schedule.call('my-task', () => {}).cron('0 0 * * *') // Daily at midnight
|
|
462
|
+
* Schedule.call('my-task', () => {}).cron('*\/5 * * * *') // Every 5 minutes
|
|
463
|
+
* Schedule.call('my-task', () => {}).cron('0 *\/2 * * *') // Every 2 hours
|
|
464
|
+
*/
|
|
465
|
+
cron(pattern) {
|
|
466
|
+
this.cronPattern = pattern;
|
|
467
|
+
return this;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Schedule to run at a specific interval.
|
|
471
|
+
* For longer intervals (hour, day, week, etc.), you can customize when they run.
|
|
472
|
+
*
|
|
473
|
+
* @param interval - The schedule interval
|
|
474
|
+
* @param options - Options to customize the cron pattern
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* Schedule.call('my-task', () => {}).every('minute')
|
|
478
|
+
* Schedule.call('my-task', () => {}).every('hour', { minute: 30 })
|
|
479
|
+
* Schedule.call('my-task', () => {}).every('day', { hour: 14, minute: 30 })
|
|
480
|
+
* Schedule.call('my-task', () => {}).every('week', { dayOfWeek: 1, hour: 9 })
|
|
481
|
+
*/
|
|
482
|
+
every(interval, options) {
|
|
483
|
+
this.interval = interval;
|
|
484
|
+
this.intervalOptions = options;
|
|
485
|
+
this.cronPattern = intervalToCron(interval, options);
|
|
486
|
+
return this;
|
|
487
|
+
}
|
|
488
|
+
on(dayOfWeek) {
|
|
489
|
+
var _a;
|
|
490
|
+
const valid = [
|
|
491
|
+
//
|
|
492
|
+
"week",
|
|
493
|
+
"month"
|
|
494
|
+
];
|
|
495
|
+
if (!valid.includes(this.interval)) {
|
|
496
|
+
throw new Error(
|
|
497
|
+
`.on() can only be used for weekly intervals or larger. Current interval: '${this.interval}'`
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
this.intervalOptions = __spreadProps(__spreadValues({}, (_a = this.intervalOptions) != null ? _a : {}), { dayOfWeek });
|
|
501
|
+
this.cronPattern = intervalToCron(this.interval, this.intervalOptions);
|
|
502
|
+
return this;
|
|
503
|
+
}
|
|
504
|
+
at(time) {
|
|
505
|
+
var _a;
|
|
506
|
+
const valid = [
|
|
507
|
+
"day",
|
|
508
|
+
"week",
|
|
509
|
+
"sunday",
|
|
510
|
+
"monday",
|
|
511
|
+
"tuesday",
|
|
512
|
+
"wednesday",
|
|
513
|
+
"thursday",
|
|
514
|
+
"friday",
|
|
515
|
+
"saturday",
|
|
516
|
+
"month",
|
|
517
|
+
"last day of month"
|
|
518
|
+
];
|
|
519
|
+
if (!valid.includes(this.interval)) {
|
|
520
|
+
throw new Error(
|
|
521
|
+
`.at() can only be used for daily intervals or larger. Current interval: '${this.interval}'`
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
const [hour, minute] = parseTime(time);
|
|
525
|
+
this.intervalOptions = __spreadProps(__spreadValues({}, (_a = this.intervalOptions) != null ? _a : {}), { hour, minute });
|
|
526
|
+
this.cronPattern = intervalToCron(this.interval, this.intervalOptions);
|
|
527
|
+
return this;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Set the duration during which other instances
|
|
531
|
+
* of the same task will be prevented from running.
|
|
532
|
+
*
|
|
533
|
+
* This should be roughly the duration of the task execution or longer
|
|
534
|
+
* since the lock will be released automatically after the task execution.
|
|
535
|
+
*
|
|
536
|
+
* @param ttl - The lock duration
|
|
537
|
+
*
|
|
538
|
+
* @example
|
|
539
|
+
* Schedule.call('my-task', () => {}).lockFor('10s')
|
|
540
|
+
*/
|
|
541
|
+
lockFor(ttl) {
|
|
542
|
+
this.distributedLockOptions.ttl = ttl;
|
|
543
|
+
return this;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Allow overlapping executions of the same task.
|
|
547
|
+
*
|
|
548
|
+
* @example
|
|
549
|
+
* Schedule.call('my-task', () => {}).overlapping()
|
|
550
|
+
*/
|
|
551
|
+
overlapping() {
|
|
552
|
+
this.distributedLockOptions.overlap = true;
|
|
553
|
+
return this;
|
|
554
|
+
}
|
|
555
|
+
execute() {
|
|
556
|
+
return __async(this, null, function* () {
|
|
557
|
+
if (!this.cronPattern) {
|
|
558
|
+
throw new Error(
|
|
559
|
+
"No schedule pattern defined. To schedule a task, set interval explicitly."
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
ScheduleRegistry.add(
|
|
563
|
+
this.name,
|
|
564
|
+
new Cron(this.cronPattern, () => __async(this, null, function* () {
|
|
565
|
+
if (this.distributedLockOptions.overlap) {
|
|
566
|
+
yield this.cb();
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
const key = this.distributedLockOptions.key(this.name);
|
|
570
|
+
const ttl = this.distributedLockOptions.ttl;
|
|
571
|
+
const lockProvider = this.lockProviderResolver();
|
|
572
|
+
const lock = lockProvider.createLock(key, ttl);
|
|
573
|
+
const acquired = yield lock.acquireImmediately();
|
|
574
|
+
if (!acquired) {
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
try {
|
|
578
|
+
if (this.distributedLockOptions.handOff) {
|
|
579
|
+
yield this.cb(lock.serialize());
|
|
580
|
+
} else {
|
|
581
|
+
yield this.cb();
|
|
582
|
+
yield lock.forceRelease();
|
|
583
|
+
}
|
|
584
|
+
} catch (error) {
|
|
585
|
+
yield lock.forceRelease();
|
|
586
|
+
throw error;
|
|
587
|
+
} finally {
|
|
588
|
+
}
|
|
589
|
+
}))
|
|
590
|
+
);
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* By defining the "then" method, PendingDispatch becomes "thenable",
|
|
595
|
+
* allowing it to trigger automatically when await is called.
|
|
596
|
+
*/
|
|
597
|
+
then(onfulfilled, onrejected) {
|
|
598
|
+
return __async(this, null, function* () {
|
|
599
|
+
return this.execute().then(onfulfilled, onrejected);
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
// src/schedule/pending_job_schedule.ts
|
|
605
|
+
var PendingJobSchedule = class _PendingJobSchedule extends PendingSchedule {
|
|
606
|
+
constructor(job, payload, lockProviderResolver) {
|
|
607
|
+
super(
|
|
608
|
+
job.name,
|
|
609
|
+
(serializedLock) => __async(this, null, function* () {
|
|
610
|
+
if (serializedLock) {
|
|
611
|
+
this.payload._lock = serializedLock;
|
|
612
|
+
}
|
|
613
|
+
yield this.dispatch.then(void 0, (error) => {
|
|
614
|
+
throw error;
|
|
615
|
+
});
|
|
616
|
+
}),
|
|
617
|
+
lockProviderResolver
|
|
618
|
+
);
|
|
619
|
+
this.job = job;
|
|
620
|
+
this.payload = payload;
|
|
621
|
+
this.lockProviderResolver = lockProviderResolver;
|
|
622
|
+
/**
|
|
623
|
+
* Use composition pattern and store pending
|
|
624
|
+
* job dispatch inside a pending schedule.
|
|
625
|
+
*/
|
|
626
|
+
__publicField(this, "dispatch");
|
|
627
|
+
__publicField(this, "_connection");
|
|
628
|
+
__publicField(this, "_queue");
|
|
629
|
+
this.job = job;
|
|
630
|
+
this.payload = payload;
|
|
631
|
+
this.dispatch = new PendingDispatch(job, payload);
|
|
632
|
+
this.distributedLockOptions.handOff = true;
|
|
633
|
+
}
|
|
634
|
+
get jobName() {
|
|
635
|
+
return `${this._connection}_${this._queue}_${this.job.name}`;
|
|
636
|
+
}
|
|
637
|
+
onConnection(connection) {
|
|
638
|
+
this._connection = connection;
|
|
639
|
+
this.dispatch.onConnection(connection);
|
|
640
|
+
return this;
|
|
641
|
+
}
|
|
642
|
+
onQueue(queue) {
|
|
643
|
+
this._queue = queue;
|
|
644
|
+
this.dispatch.onQueue(queue);
|
|
645
|
+
return this;
|
|
646
|
+
}
|
|
647
|
+
// public withQueueServiceResolver(queueServiceResolver: () => Promise<Queue>) {
|
|
648
|
+
// this.dispatch.withQueueServiceResolver(queueServiceResolver)
|
|
649
|
+
// return this
|
|
650
|
+
// }
|
|
651
|
+
execute() {
|
|
652
|
+
return __async(this, null, function* () {
|
|
653
|
+
var _a, _b, _c;
|
|
654
|
+
const queueServiceResolver = this.job.getQueueServiceResolver;
|
|
655
|
+
if (queueServiceResolver) {
|
|
656
|
+
const queue = yield queueServiceResolver();
|
|
657
|
+
const connection = (_a = this.job.options.connection) != null ? _a : queue.getDefaultConnection();
|
|
658
|
+
const connectionLockService = queue.getLockProvider(connection);
|
|
659
|
+
if (connectionLockService) {
|
|
660
|
+
this.lockProviderResolver = () => connectionLockService;
|
|
661
|
+
}
|
|
662
|
+
if (this.job.id) {
|
|
663
|
+
queue.registerScheduledJob(this.job.id);
|
|
664
|
+
}
|
|
665
|
+
this._connection = (_b = this._connection) != null ? _b : queue.getDefaultConnection();
|
|
666
|
+
this._queue = (_c = this._queue) != null ? _c : queue.getDefaultQueue();
|
|
667
|
+
}
|
|
668
|
+
this.name = this.jobName;
|
|
669
|
+
yield __superGet(_PendingJobSchedule.prototype, this, "execute").call(this);
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
// src/schedule/schedule.ts
|
|
675
|
+
import { LockFactory } from "@verrou/core";
|
|
676
|
+
import { memoryStore } from "@verrou/core/drivers/memory";
|
|
677
|
+
var defaultScheduleLockProvider = new LockFactory(
|
|
678
|
+
memoryStore().factory()
|
|
679
|
+
);
|
|
680
|
+
var Schedule = class {
|
|
681
|
+
/**
|
|
682
|
+
* Set a custom lock provider resolver for distributed locking.
|
|
683
|
+
*
|
|
684
|
+
* This allows dynamic resolution of lock provider instances, useful when
|
|
685
|
+
* integrating with Queue or other services that manage lock instances.
|
|
686
|
+
*
|
|
687
|
+
* @param resolver - Function that returns a LockFactory instance
|
|
688
|
+
*
|
|
689
|
+
* @example
|
|
690
|
+
* import { LockFactory } from '@verrou/core'
|
|
691
|
+
* import { redisStore } from '@verrou/core/drivers/redis'
|
|
692
|
+
*
|
|
693
|
+
* const customLockProvider = new LockFactory(
|
|
694
|
+
* redisStore({ connection: redisClient })
|
|
695
|
+
* )
|
|
696
|
+
*
|
|
697
|
+
* Schedule.setLockProviderResolver(() => customLockProvider)
|
|
698
|
+
*/
|
|
699
|
+
static setLockProviderResolver(resolver) {
|
|
700
|
+
this.defaultLockProviderResolver = resolver;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Get the current lock provider instance from the resolver.
|
|
704
|
+
* @internal
|
|
705
|
+
*/
|
|
706
|
+
static getLockProvider() {
|
|
707
|
+
return this.defaultLockProviderResolver();
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Clear all scheduled tasks (or specific one if name is specified).
|
|
711
|
+
*
|
|
712
|
+
* @param name - The name of the task to clear
|
|
713
|
+
*
|
|
714
|
+
* @example
|
|
715
|
+
* Schedule.clear() // Clear all tasks
|
|
716
|
+
* Schedule.clear('my-task') // Clear specific task
|
|
717
|
+
*/
|
|
718
|
+
static clear(name) {
|
|
719
|
+
if (name) {
|
|
720
|
+
ScheduleRegistry.clear(name);
|
|
721
|
+
} else {
|
|
722
|
+
Object.keys(ScheduleRegistry.all()).forEach(
|
|
723
|
+
(name2) => ScheduleRegistry.clear(name2)
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Schedule a callback to run at specified intervals.
|
|
729
|
+
*
|
|
730
|
+
* @param name - Unique identifier for the task (required for distributed systems)
|
|
731
|
+
* @param cb - The callback function to execute
|
|
732
|
+
*
|
|
733
|
+
* @example
|
|
734
|
+
* // Using cron pattern
|
|
735
|
+
* const cleanupUsers = async () => { ... }
|
|
736
|
+
* Schedule.call('cleanup-users', cleanupUsers).cron('0 0 * * *')
|
|
737
|
+
*
|
|
738
|
+
* // Using convenience methods
|
|
739
|
+
* Schedule.call('hourly-task', () => { ... }).hourly()
|
|
740
|
+
* Schedule.call('daily-task', () => { ... }).daily()
|
|
741
|
+
*/
|
|
742
|
+
static call(name, cb) {
|
|
743
|
+
return new PendingSchedule(name, cb, this.defaultLockProviderResolver);
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Schedule a job to run at specified intervals.
|
|
747
|
+
*
|
|
748
|
+
* You can specify the connection and queue to use for the job
|
|
749
|
+
* the same way you would dispatch a job.
|
|
750
|
+
*
|
|
751
|
+
* @param job - The job class to schedule
|
|
752
|
+
* @param payload - The payload to pass to the job
|
|
753
|
+
*
|
|
754
|
+
* @example
|
|
755
|
+
* Schedule.job(TestJob, { arg1: 'hello', arg2: 1 }).every('minute')
|
|
756
|
+
* Schedule.job(TestJob, { arg1: 'hello', arg2: 1 })
|
|
757
|
+
* .onConnection('main')
|
|
758
|
+
* .onQueue('default')
|
|
759
|
+
* .every('minute')
|
|
760
|
+
*/
|
|
761
|
+
static job(job, payload) {
|
|
762
|
+
return new PendingJobSchedule(
|
|
763
|
+
new job(),
|
|
764
|
+
payload,
|
|
765
|
+
this.defaultLockProviderResolver
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
/**
|
|
770
|
+
* Default lock provider resolver for distributed locking.
|
|
771
|
+
* Returns the default memory-based instance if not overridden.
|
|
772
|
+
*/
|
|
773
|
+
__publicField(Schedule, "defaultLockProviderResolver", () => defaultScheduleLockProvider);
|
|
774
|
+
|
|
775
|
+
// src/queue/queue.ts
|
|
776
|
+
var Queue = class {
|
|
777
|
+
constructor(config) {
|
|
778
|
+
this.config = config;
|
|
779
|
+
__publicField(this, "drivers", /* @__PURE__ */ new Map());
|
|
780
|
+
__publicField(this, "started", false);
|
|
781
|
+
__publicField(this, "logger");
|
|
782
|
+
__publicField(this, "scheduledJobs", /* @__PURE__ */ new Set());
|
|
783
|
+
__publicField(this, "lockFactories", /* @__PURE__ */ new Map());
|
|
784
|
+
this.logger = (config == null ? void 0 : config.logger) || createDefaultLogger("queue");
|
|
785
|
+
for (const [connection, driverConfig] of Object.entries(
|
|
786
|
+
this.config.connections
|
|
787
|
+
)) {
|
|
788
|
+
this.logger.trace(
|
|
789
|
+
{ connection, driver: driverConfig.driver },
|
|
790
|
+
"Creating queue driver"
|
|
791
|
+
);
|
|
792
|
+
const driver = this.createDriver(driverConfig);
|
|
793
|
+
driver.connection = connection;
|
|
794
|
+
this.drivers.set(driver.connection, driver);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
createDriver(config) {
|
|
798
|
+
const { constructor: driverConstructor, config: driverConfig } = config.driver;
|
|
799
|
+
const driver = new driverConstructor(
|
|
800
|
+
this.config,
|
|
801
|
+
config.queues,
|
|
802
|
+
driverConfig
|
|
803
|
+
);
|
|
804
|
+
driver.setLogger(this.logger);
|
|
805
|
+
return driver;
|
|
806
|
+
}
|
|
807
|
+
start() {
|
|
808
|
+
return __async(this, null, function* () {
|
|
809
|
+
if (this.started) {
|
|
810
|
+
this.logger.warn("Queue service already started");
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
for (const [connection, driverConfig] of Object.entries(
|
|
814
|
+
this.config.connections
|
|
815
|
+
)) {
|
|
816
|
+
const driver = this.drivers.get(connection);
|
|
817
|
+
if (!driver) {
|
|
818
|
+
throw new Error(`Driver not found for connection: ${connection}.`);
|
|
819
|
+
}
|
|
820
|
+
if (!driverConfig.lockProvider) {
|
|
821
|
+
const lockFactory = driver.createLockProvider();
|
|
822
|
+
if (lockFactory) {
|
|
823
|
+
this.lockFactories.set(connection, lockFactory);
|
|
824
|
+
this.logger.trace(
|
|
825
|
+
{ connection, driver: driverConfig.driver },
|
|
826
|
+
"Created lock factory for driver"
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
} else {
|
|
830
|
+
this.lockFactories.set(
|
|
831
|
+
connection,
|
|
832
|
+
driverConfig.lockProvider
|
|
833
|
+
);
|
|
834
|
+
this.logger.trace(
|
|
835
|
+
{ connection, driver: driverConfig.driver },
|
|
836
|
+
"Using explicitly configured lock provider for driver"
|
|
837
|
+
);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
for (const job of this.config.jobs) {
|
|
841
|
+
yield this.register(job);
|
|
842
|
+
}
|
|
843
|
+
this.started = true;
|
|
844
|
+
for (const [connection, driver] of this.drivers) {
|
|
845
|
+
this.logger.trace({ connection }, "Starting queue connection");
|
|
846
|
+
yield driver.start();
|
|
847
|
+
}
|
|
848
|
+
this.logger.trace(
|
|
849
|
+
{ connections: Array.from(this.drivers.keys()) },
|
|
850
|
+
"Queue service started"
|
|
851
|
+
);
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
stop() {
|
|
855
|
+
return __async(this, arguments, function* (options = {
|
|
856
|
+
graceful: true,
|
|
857
|
+
timeout: 3e4
|
|
858
|
+
}) {
|
|
859
|
+
if (!this.started) {
|
|
860
|
+
this.logger.warn("Queue service not started");
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
this.logger.trace(
|
|
864
|
+
{ count: this.scheduledJobs.size },
|
|
865
|
+
"Cleared scheduled jobs for the queue"
|
|
866
|
+
);
|
|
867
|
+
for (const id of this.scheduledJobs) {
|
|
868
|
+
Schedule.clear(id);
|
|
869
|
+
}
|
|
870
|
+
this.scheduledJobs.clear();
|
|
871
|
+
for (const [connection, driver] of this.drivers) {
|
|
872
|
+
this.logger.trace({ connection }, "Stopping queue connection");
|
|
873
|
+
yield driver.stop(options);
|
|
874
|
+
}
|
|
875
|
+
for (const job of this.config.jobs) {
|
|
876
|
+
yield this.unregister(job);
|
|
877
|
+
}
|
|
878
|
+
for (const [connection, lockFactory] of this.lockFactories) {
|
|
879
|
+
const driver = this.drivers.get(connection);
|
|
880
|
+
if (!driver) {
|
|
881
|
+
throw new Error(`Driver not found for connection: ${connection}.`);
|
|
882
|
+
}
|
|
883
|
+
yield driver.destroyLockProvider(lockFactory);
|
|
884
|
+
this.lockFactories.delete(connection);
|
|
885
|
+
}
|
|
886
|
+
this.started = false;
|
|
887
|
+
this.logger.trace("Queue service stopped");
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
register(job) {
|
|
891
|
+
return __async(this, null, function* () {
|
|
892
|
+
for (const [_, driver] of this.drivers) {
|
|
893
|
+
yield driver.register(job);
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
unregister(job) {
|
|
898
|
+
return __async(this, null, function* () {
|
|
899
|
+
for (const [_, driver] of this.drivers) {
|
|
900
|
+
yield driver.unregister(job);
|
|
901
|
+
}
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
enqueue(job, payload) {
|
|
905
|
+
return __async(this, null, function* () {
|
|
906
|
+
if (this.drivers.size === 0) {
|
|
907
|
+
throw new Error("No queue drivers available.");
|
|
908
|
+
}
|
|
909
|
+
const driver = job.options.connection ? this.drivers.get(job.options.connection) : this.drivers.values().next().value;
|
|
910
|
+
if (!driver) {
|
|
911
|
+
throw new Error(
|
|
912
|
+
`No driver found for connection: ${job.options.connection}.`
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
if (!job.options.queue) {
|
|
916
|
+
job.options.queue = driver.getDefaultQueue();
|
|
917
|
+
}
|
|
918
|
+
yield driver.enqueue(job, payload);
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* Get the default connection name.
|
|
923
|
+
*
|
|
924
|
+
* Returns the name of the first available connection.
|
|
925
|
+
* Throws an error if no connections are available.
|
|
926
|
+
*/
|
|
927
|
+
getDefaultConnection() {
|
|
928
|
+
if (this.drivers.size === 0) {
|
|
929
|
+
throw new Error(`No queue drivers available.`);
|
|
930
|
+
}
|
|
931
|
+
return this.drivers.keys().next().value;
|
|
932
|
+
}
|
|
933
|
+
getDefaultQueue() {
|
|
934
|
+
var _a;
|
|
935
|
+
if (this.drivers.size === 0) {
|
|
936
|
+
throw new Error(`No queue drivers available.`);
|
|
937
|
+
}
|
|
938
|
+
return (_a = this.drivers.values().next().value) == null ? void 0 : _a.getDefaultQueue();
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Get the lock factory instance for a specific connection.
|
|
942
|
+
* Returns the explicitly configured lock provider or the auto-created lock factory.
|
|
943
|
+
* Throws an error if no lock factory is available.
|
|
944
|
+
*
|
|
945
|
+
* @param connection - The connection name
|
|
946
|
+
* @returns The lock factory instance
|
|
947
|
+
*/
|
|
948
|
+
getLockProvider(connection) {
|
|
949
|
+
const connectionConfig = this.config.connections[connection];
|
|
950
|
+
if (connectionConfig == null ? void 0 : connectionConfig.lockProvider) {
|
|
951
|
+
return connectionConfig.lockProvider;
|
|
952
|
+
}
|
|
953
|
+
const lockFactory = this.lockFactories.get(connection);
|
|
954
|
+
if (!lockFactory) {
|
|
955
|
+
throw new Error(`No lock provider found for connection: ${connection}.`);
|
|
956
|
+
}
|
|
957
|
+
return lockFactory;
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Register a scheduled job ID with this Queue instance.
|
|
961
|
+
* This allows the Queue to clean up scheduled jobs when it stops.
|
|
962
|
+
*/
|
|
963
|
+
registerScheduledJob(id) {
|
|
964
|
+
this.scheduledJobs.add(id);
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
export {
|
|
968
|
+
Job,
|
|
969
|
+
Logger,
|
|
970
|
+
PendingDispatch,
|
|
971
|
+
PendingJobSchedule,
|
|
972
|
+
PendingSchedule,
|
|
973
|
+
Queue,
|
|
974
|
+
QueueDriver,
|
|
975
|
+
Schedule,
|
|
976
|
+
ScheduleRegistry,
|
|
977
|
+
createDefaultLogger,
|
|
978
|
+
defaultScheduleLockProvider,
|
|
979
|
+
defineConfig,
|
|
980
|
+
getDistributedLockKey,
|
|
981
|
+
intervalToCron,
|
|
982
|
+
parseTime
|
|
983
|
+
};
|
|
984
|
+
//# sourceMappingURL=index.js.map
|