@trigger.dev/redis-worker 4.0.0-v4-beta.20 → 4.0.0-v4-beta.22
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/dist/index.cjs +607 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -9
- package/dist/index.d.ts +59 -9
- package/dist/index.js +607 -79
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -7,7 +7,8 @@ import { webcrypto } from 'node:crypto';
|
|
|
7
7
|
import '@trigger.dev/core/v3/utils/flattenAttributes';
|
|
8
8
|
import { calculateNextRetryDelay } from '@trigger.dev/core/v3';
|
|
9
9
|
import { shutdownManager } from '@trigger.dev/core/v3/serverOnly';
|
|
10
|
-
import {
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { parseExpression } from 'cron-parser';
|
|
11
12
|
|
|
12
13
|
const require = createRequire(import.meta.url || process.cwd() + '/index.js');
|
|
13
14
|
var __create = Object.create;
|
|
@@ -8737,7 +8738,7 @@ var require_Redis = __commonJS({
|
|
|
8737
8738
|
var lodash_1 = require_lodash3();
|
|
8738
8739
|
var Deque = require_denque();
|
|
8739
8740
|
var debug = (0, utils_1.Debug)("redis");
|
|
8740
|
-
var
|
|
8741
|
+
var Redis4 = class _Redis extends Commander_1.default {
|
|
8741
8742
|
constructor(arg1, arg2, arg3) {
|
|
8742
8743
|
super();
|
|
8743
8744
|
this.status = "wait";
|
|
@@ -9300,12 +9301,12 @@ var require_Redis = __commonJS({
|
|
|
9300
9301
|
}).catch(lodash_1.noop);
|
|
9301
9302
|
}
|
|
9302
9303
|
};
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
(0, applyMixin_1.default)(
|
|
9307
|
-
(0, transaction_1.addTransactionSupport)(
|
|
9308
|
-
exports.default =
|
|
9304
|
+
Redis4.Cluster = cluster_1.default;
|
|
9305
|
+
Redis4.Command = Command_1.default;
|
|
9306
|
+
Redis4.defaultOptions = RedisOptions_1.DEFAULT_REDIS_OPTIONS;
|
|
9307
|
+
(0, applyMixin_1.default)(Redis4, events_1.EventEmitter);
|
|
9308
|
+
(0, transaction_1.addTransactionSupport)(Redis4.prototype);
|
|
9309
|
+
exports.default = Redis4;
|
|
9309
9310
|
}
|
|
9310
9311
|
});
|
|
9311
9312
|
|
|
@@ -9503,6 +9504,39 @@ var SimpleQueue = class {
|
|
|
9503
9504
|
throw e;
|
|
9504
9505
|
}
|
|
9505
9506
|
}
|
|
9507
|
+
async enqueueOnce({
|
|
9508
|
+
id,
|
|
9509
|
+
job,
|
|
9510
|
+
item,
|
|
9511
|
+
attempt,
|
|
9512
|
+
availableAt,
|
|
9513
|
+
visibilityTimeoutMs
|
|
9514
|
+
}) {
|
|
9515
|
+
if (!id) {
|
|
9516
|
+
throw new Error("enqueueOnce requires an id");
|
|
9517
|
+
}
|
|
9518
|
+
try {
|
|
9519
|
+
const score = availableAt ? availableAt.getTime() : Date.now();
|
|
9520
|
+
const deduplicationKey = nanoid();
|
|
9521
|
+
const serializedItem = JSON.stringify({
|
|
9522
|
+
job,
|
|
9523
|
+
item,
|
|
9524
|
+
visibilityTimeoutMs,
|
|
9525
|
+
attempt,
|
|
9526
|
+
deduplicationKey
|
|
9527
|
+
});
|
|
9528
|
+
const result = await this.redis.enqueueItemOnce(`queue`, `items`, id, score, serializedItem);
|
|
9529
|
+
return result === 1;
|
|
9530
|
+
} catch (e) {
|
|
9531
|
+
this.logger.error(`SimpleQueue ${this.name}.enqueueOnce(): error enqueuing`, {
|
|
9532
|
+
queue: this.name,
|
|
9533
|
+
error: e,
|
|
9534
|
+
id,
|
|
9535
|
+
item
|
|
9536
|
+
});
|
|
9537
|
+
throw e;
|
|
9538
|
+
}
|
|
9539
|
+
}
|
|
9506
9540
|
async dequeue(count = 1) {
|
|
9507
9541
|
const now = Date.now();
|
|
9508
9542
|
try {
|
|
@@ -9525,7 +9559,8 @@ var SimpleQueue = class {
|
|
|
9525
9559
|
id,
|
|
9526
9560
|
item: parsedItem,
|
|
9527
9561
|
job: parsedItem.job,
|
|
9528
|
-
timestamp
|
|
9562
|
+
timestamp,
|
|
9563
|
+
availableJobs: Object.keys(this.schema)
|
|
9529
9564
|
});
|
|
9530
9565
|
continue;
|
|
9531
9566
|
}
|
|
@@ -9606,8 +9641,30 @@ var SimpleQueue = class {
|
|
|
9606
9641
|
throw e;
|
|
9607
9642
|
}
|
|
9608
9643
|
}
|
|
9644
|
+
async getJob(id) {
|
|
9645
|
+
const result = await this.redis.getJob(`queue`, `items`, id);
|
|
9646
|
+
if (!result) {
|
|
9647
|
+
return null;
|
|
9648
|
+
}
|
|
9649
|
+
const [_, score, serializedItem] = result;
|
|
9650
|
+
const item = JSON.parse(serializedItem);
|
|
9651
|
+
return {
|
|
9652
|
+
id,
|
|
9653
|
+
job: item.job,
|
|
9654
|
+
item: item.item,
|
|
9655
|
+
visibilityTimeoutMs: item.visibilityTimeoutMs,
|
|
9656
|
+
attempt: item.attempt ?? 0,
|
|
9657
|
+
timestamp: new Date(Number(score)),
|
|
9658
|
+
deduplicationKey: item.deduplicationKey ?? void 0
|
|
9659
|
+
};
|
|
9660
|
+
}
|
|
9609
9661
|
async moveToDeadLetterQueue(id, errorMessage) {
|
|
9610
9662
|
try {
|
|
9663
|
+
this.logger.debug(`SimpleQueue ${this.name}.moveToDeadLetterQueue(): moving item to DLQ`, {
|
|
9664
|
+
queue: this.name,
|
|
9665
|
+
id,
|
|
9666
|
+
errorMessage
|
|
9667
|
+
});
|
|
9611
9668
|
const result = await this.redis.moveToDeadLetterQueue(
|
|
9612
9669
|
`queue`,
|
|
9613
9670
|
`items`,
|
|
@@ -9728,6 +9785,25 @@ var SimpleQueue = class {
|
|
|
9728
9785
|
return dequeued
|
|
9729
9786
|
`
|
|
9730
9787
|
});
|
|
9788
|
+
this.redis.defineCommand("getJob", {
|
|
9789
|
+
numberOfKeys: 2,
|
|
9790
|
+
lua: `
|
|
9791
|
+
local queue = KEYS[1]
|
|
9792
|
+
local items = KEYS[2]
|
|
9793
|
+
local jobId = ARGV[1]
|
|
9794
|
+
|
|
9795
|
+
local serializedItem = redis.call('HGET', items, jobId)
|
|
9796
|
+
|
|
9797
|
+
if serializedItem == false then
|
|
9798
|
+
return nil
|
|
9799
|
+
end
|
|
9800
|
+
|
|
9801
|
+
-- get the score from the queue sorted set
|
|
9802
|
+
local score = redis.call('ZSCORE', queue, jobId)
|
|
9803
|
+
|
|
9804
|
+
return { jobId, score, serializedItem }
|
|
9805
|
+
`
|
|
9806
|
+
});
|
|
9731
9807
|
this.redis.defineCommand("ackItem", {
|
|
9732
9808
|
numberOfKeys: 2,
|
|
9733
9809
|
lua: `
|
|
@@ -9817,6 +9893,25 @@ var SimpleQueue = class {
|
|
|
9817
9893
|
return 1
|
|
9818
9894
|
`
|
|
9819
9895
|
});
|
|
9896
|
+
this.redis.defineCommand("enqueueItemOnce", {
|
|
9897
|
+
numberOfKeys: 2,
|
|
9898
|
+
lua: `
|
|
9899
|
+
local queue = KEYS[1]
|
|
9900
|
+
local items = KEYS[2]
|
|
9901
|
+
local id = ARGV[1]
|
|
9902
|
+
local score = ARGV[2]
|
|
9903
|
+
local serializedItem = ARGV[3]
|
|
9904
|
+
|
|
9905
|
+
-- Only add if not exists
|
|
9906
|
+
local added = redis.call('HSETNX', items, id, serializedItem)
|
|
9907
|
+
if added == 1 then
|
|
9908
|
+
redis.call('ZADD', queue, 'NX', score, id)
|
|
9909
|
+
return 1
|
|
9910
|
+
else
|
|
9911
|
+
return 0
|
|
9912
|
+
end
|
|
9913
|
+
`
|
|
9914
|
+
});
|
|
9820
9915
|
}
|
|
9821
9916
|
};
|
|
9822
9917
|
|
|
@@ -10173,6 +10268,173 @@ var BaseContext = (
|
|
|
10173
10268
|
);
|
|
10174
10269
|
var ROOT_CONTEXT = new BaseContext();
|
|
10175
10270
|
|
|
10271
|
+
// ../../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeter.js
|
|
10272
|
+
var __extends = /* @__PURE__ */ function() {
|
|
10273
|
+
var extendStatics = function(d, b) {
|
|
10274
|
+
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
|
|
10275
|
+
d2.__proto__ = b2;
|
|
10276
|
+
} || function(d2, b2) {
|
|
10277
|
+
for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p];
|
|
10278
|
+
};
|
|
10279
|
+
return extendStatics(d, b);
|
|
10280
|
+
};
|
|
10281
|
+
return function(d, b) {
|
|
10282
|
+
if (typeof b !== "function" && b !== null)
|
|
10283
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
10284
|
+
extendStatics(d, b);
|
|
10285
|
+
function __() {
|
|
10286
|
+
this.constructor = d;
|
|
10287
|
+
}
|
|
10288
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
10289
|
+
};
|
|
10290
|
+
}();
|
|
10291
|
+
var NoopMeter = (
|
|
10292
|
+
/** @class */
|
|
10293
|
+
function() {
|
|
10294
|
+
function NoopMeter2() {
|
|
10295
|
+
}
|
|
10296
|
+
NoopMeter2.prototype.createGauge = function(_name, _options) {
|
|
10297
|
+
return NOOP_GAUGE_METRIC;
|
|
10298
|
+
};
|
|
10299
|
+
NoopMeter2.prototype.createHistogram = function(_name, _options) {
|
|
10300
|
+
return NOOP_HISTOGRAM_METRIC;
|
|
10301
|
+
};
|
|
10302
|
+
NoopMeter2.prototype.createCounter = function(_name, _options) {
|
|
10303
|
+
return NOOP_COUNTER_METRIC;
|
|
10304
|
+
};
|
|
10305
|
+
NoopMeter2.prototype.createUpDownCounter = function(_name, _options) {
|
|
10306
|
+
return NOOP_UP_DOWN_COUNTER_METRIC;
|
|
10307
|
+
};
|
|
10308
|
+
NoopMeter2.prototype.createObservableGauge = function(_name, _options) {
|
|
10309
|
+
return NOOP_OBSERVABLE_GAUGE_METRIC;
|
|
10310
|
+
};
|
|
10311
|
+
NoopMeter2.prototype.createObservableCounter = function(_name, _options) {
|
|
10312
|
+
return NOOP_OBSERVABLE_COUNTER_METRIC;
|
|
10313
|
+
};
|
|
10314
|
+
NoopMeter2.prototype.createObservableUpDownCounter = function(_name, _options) {
|
|
10315
|
+
return NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC;
|
|
10316
|
+
};
|
|
10317
|
+
NoopMeter2.prototype.addBatchObservableCallback = function(_callback, _observables) {
|
|
10318
|
+
};
|
|
10319
|
+
NoopMeter2.prototype.removeBatchObservableCallback = function(_callback) {
|
|
10320
|
+
};
|
|
10321
|
+
return NoopMeter2;
|
|
10322
|
+
}()
|
|
10323
|
+
);
|
|
10324
|
+
var NoopMetric = (
|
|
10325
|
+
/** @class */
|
|
10326
|
+
/* @__PURE__ */ function() {
|
|
10327
|
+
function NoopMetric2() {
|
|
10328
|
+
}
|
|
10329
|
+
return NoopMetric2;
|
|
10330
|
+
}()
|
|
10331
|
+
);
|
|
10332
|
+
var NoopCounterMetric = (
|
|
10333
|
+
/** @class */
|
|
10334
|
+
function(_super) {
|
|
10335
|
+
__extends(NoopCounterMetric2, _super);
|
|
10336
|
+
function NoopCounterMetric2() {
|
|
10337
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
10338
|
+
}
|
|
10339
|
+
NoopCounterMetric2.prototype.add = function(_value, _attributes) {
|
|
10340
|
+
};
|
|
10341
|
+
return NoopCounterMetric2;
|
|
10342
|
+
}(NoopMetric)
|
|
10343
|
+
);
|
|
10344
|
+
var NoopUpDownCounterMetric = (
|
|
10345
|
+
/** @class */
|
|
10346
|
+
function(_super) {
|
|
10347
|
+
__extends(NoopUpDownCounterMetric2, _super);
|
|
10348
|
+
function NoopUpDownCounterMetric2() {
|
|
10349
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
10350
|
+
}
|
|
10351
|
+
NoopUpDownCounterMetric2.prototype.add = function(_value, _attributes) {
|
|
10352
|
+
};
|
|
10353
|
+
return NoopUpDownCounterMetric2;
|
|
10354
|
+
}(NoopMetric)
|
|
10355
|
+
);
|
|
10356
|
+
var NoopGaugeMetric = (
|
|
10357
|
+
/** @class */
|
|
10358
|
+
function(_super) {
|
|
10359
|
+
__extends(NoopGaugeMetric2, _super);
|
|
10360
|
+
function NoopGaugeMetric2() {
|
|
10361
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
10362
|
+
}
|
|
10363
|
+
NoopGaugeMetric2.prototype.record = function(_value, _attributes) {
|
|
10364
|
+
};
|
|
10365
|
+
return NoopGaugeMetric2;
|
|
10366
|
+
}(NoopMetric)
|
|
10367
|
+
);
|
|
10368
|
+
var NoopHistogramMetric = (
|
|
10369
|
+
/** @class */
|
|
10370
|
+
function(_super) {
|
|
10371
|
+
__extends(NoopHistogramMetric2, _super);
|
|
10372
|
+
function NoopHistogramMetric2() {
|
|
10373
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
10374
|
+
}
|
|
10375
|
+
NoopHistogramMetric2.prototype.record = function(_value, _attributes) {
|
|
10376
|
+
};
|
|
10377
|
+
return NoopHistogramMetric2;
|
|
10378
|
+
}(NoopMetric)
|
|
10379
|
+
);
|
|
10380
|
+
var NoopObservableMetric = (
|
|
10381
|
+
/** @class */
|
|
10382
|
+
function() {
|
|
10383
|
+
function NoopObservableMetric2() {
|
|
10384
|
+
}
|
|
10385
|
+
NoopObservableMetric2.prototype.addCallback = function(_callback) {
|
|
10386
|
+
};
|
|
10387
|
+
NoopObservableMetric2.prototype.removeCallback = function(_callback) {
|
|
10388
|
+
};
|
|
10389
|
+
return NoopObservableMetric2;
|
|
10390
|
+
}()
|
|
10391
|
+
);
|
|
10392
|
+
var NoopObservableCounterMetric = (
|
|
10393
|
+
/** @class */
|
|
10394
|
+
function(_super) {
|
|
10395
|
+
__extends(NoopObservableCounterMetric2, _super);
|
|
10396
|
+
function NoopObservableCounterMetric2() {
|
|
10397
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
10398
|
+
}
|
|
10399
|
+
return NoopObservableCounterMetric2;
|
|
10400
|
+
}(NoopObservableMetric)
|
|
10401
|
+
);
|
|
10402
|
+
var NoopObservableGaugeMetric = (
|
|
10403
|
+
/** @class */
|
|
10404
|
+
function(_super) {
|
|
10405
|
+
__extends(NoopObservableGaugeMetric2, _super);
|
|
10406
|
+
function NoopObservableGaugeMetric2() {
|
|
10407
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
10408
|
+
}
|
|
10409
|
+
return NoopObservableGaugeMetric2;
|
|
10410
|
+
}(NoopObservableMetric)
|
|
10411
|
+
);
|
|
10412
|
+
var NoopObservableUpDownCounterMetric = (
|
|
10413
|
+
/** @class */
|
|
10414
|
+
function(_super) {
|
|
10415
|
+
__extends(NoopObservableUpDownCounterMetric2, _super);
|
|
10416
|
+
function NoopObservableUpDownCounterMetric2() {
|
|
10417
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
10418
|
+
}
|
|
10419
|
+
return NoopObservableUpDownCounterMetric2;
|
|
10420
|
+
}(NoopObservableMetric)
|
|
10421
|
+
);
|
|
10422
|
+
var NOOP_METER = new NoopMeter();
|
|
10423
|
+
var NOOP_COUNTER_METRIC = new NoopCounterMetric();
|
|
10424
|
+
var NOOP_GAUGE_METRIC = new NoopGaugeMetric();
|
|
10425
|
+
var NOOP_HISTOGRAM_METRIC = new NoopHistogramMetric();
|
|
10426
|
+
var NOOP_UP_DOWN_COUNTER_METRIC = new NoopUpDownCounterMetric();
|
|
10427
|
+
var NOOP_OBSERVABLE_COUNTER_METRIC = new NoopObservableCounterMetric();
|
|
10428
|
+
var NOOP_OBSERVABLE_GAUGE_METRIC = new NoopObservableGaugeMetric();
|
|
10429
|
+
var NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC = new NoopObservableUpDownCounterMetric();
|
|
10430
|
+
|
|
10431
|
+
// ../../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/metrics/Metric.js
|
|
10432
|
+
var ValueType;
|
|
10433
|
+
(function(ValueType2) {
|
|
10434
|
+
ValueType2[ValueType2["INT"] = 0] = "INT";
|
|
10435
|
+
ValueType2[ValueType2["DOUBLE"] = 1] = "DOUBLE";
|
|
10436
|
+
})(ValueType || (ValueType = {}));
|
|
10437
|
+
|
|
10176
10438
|
// ../../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/context/NoopContextManager.js
|
|
10177
10439
|
var __read3 = function(o, n) {
|
|
10178
10440
|
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
@@ -10535,8 +10797,54 @@ var SpanStatusCode;
|
|
|
10535
10797
|
SpanStatusCode2[SpanStatusCode2["ERROR"] = 2] = "ERROR";
|
|
10536
10798
|
})(SpanStatusCode || (SpanStatusCode = {}));
|
|
10537
10799
|
|
|
10800
|
+
// ../../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js
|
|
10801
|
+
var NoopMeterProvider = (
|
|
10802
|
+
/** @class */
|
|
10803
|
+
function() {
|
|
10804
|
+
function NoopMeterProvider2() {
|
|
10805
|
+
}
|
|
10806
|
+
NoopMeterProvider2.prototype.getMeter = function(_name, _version, _options) {
|
|
10807
|
+
return NOOP_METER;
|
|
10808
|
+
};
|
|
10809
|
+
return NoopMeterProvider2;
|
|
10810
|
+
}()
|
|
10811
|
+
);
|
|
10812
|
+
var NOOP_METER_PROVIDER = new NoopMeterProvider();
|
|
10813
|
+
|
|
10814
|
+
// ../../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/api/metrics.js
|
|
10815
|
+
var API_NAME3 = "metrics";
|
|
10816
|
+
var MetricsAPI = (
|
|
10817
|
+
/** @class */
|
|
10818
|
+
function() {
|
|
10819
|
+
function MetricsAPI2() {
|
|
10820
|
+
}
|
|
10821
|
+
MetricsAPI2.getInstance = function() {
|
|
10822
|
+
if (!this._instance) {
|
|
10823
|
+
this._instance = new MetricsAPI2();
|
|
10824
|
+
}
|
|
10825
|
+
return this._instance;
|
|
10826
|
+
};
|
|
10827
|
+
MetricsAPI2.prototype.setGlobalMeterProvider = function(provider) {
|
|
10828
|
+
return registerGlobal(API_NAME3, provider, DiagAPI.instance());
|
|
10829
|
+
};
|
|
10830
|
+
MetricsAPI2.prototype.getMeterProvider = function() {
|
|
10831
|
+
return getGlobal(API_NAME3) || NOOP_METER_PROVIDER;
|
|
10832
|
+
};
|
|
10833
|
+
MetricsAPI2.prototype.getMeter = function(name, version, options) {
|
|
10834
|
+
return this.getMeterProvider().getMeter(name, version, options);
|
|
10835
|
+
};
|
|
10836
|
+
MetricsAPI2.prototype.disable = function() {
|
|
10837
|
+
unregisterGlobal(API_NAME3, DiagAPI.instance());
|
|
10838
|
+
};
|
|
10839
|
+
return MetricsAPI2;
|
|
10840
|
+
}()
|
|
10841
|
+
);
|
|
10842
|
+
|
|
10843
|
+
// ../../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/metrics-api.js
|
|
10844
|
+
var metrics = MetricsAPI.getInstance();
|
|
10845
|
+
|
|
10538
10846
|
// ../../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/api/trace.js
|
|
10539
|
-
var
|
|
10847
|
+
var API_NAME4 = "trace";
|
|
10540
10848
|
var TraceAPI = (
|
|
10541
10849
|
/** @class */
|
|
10542
10850
|
function() {
|
|
@@ -10558,20 +10866,20 @@ var TraceAPI = (
|
|
|
10558
10866
|
return this._instance;
|
|
10559
10867
|
};
|
|
10560
10868
|
TraceAPI2.prototype.setGlobalTracerProvider = function(provider) {
|
|
10561
|
-
var success = registerGlobal(
|
|
10869
|
+
var success = registerGlobal(API_NAME4, this._proxyTracerProvider, DiagAPI.instance());
|
|
10562
10870
|
if (success) {
|
|
10563
10871
|
this._proxyTracerProvider.setDelegate(provider);
|
|
10564
10872
|
}
|
|
10565
10873
|
return success;
|
|
10566
10874
|
};
|
|
10567
10875
|
TraceAPI2.prototype.getTracerProvider = function() {
|
|
10568
|
-
return getGlobal(
|
|
10876
|
+
return getGlobal(API_NAME4) || this._proxyTracerProvider;
|
|
10569
10877
|
};
|
|
10570
10878
|
TraceAPI2.prototype.getTracer = function(name, version) {
|
|
10571
10879
|
return this.getTracerProvider().getTracer(name, version);
|
|
10572
10880
|
};
|
|
10573
10881
|
TraceAPI2.prototype.disable = function() {
|
|
10574
|
-
unregisterGlobal(
|
|
10882
|
+
unregisterGlobal(API_NAME4, DiagAPI.instance());
|
|
10575
10883
|
this._proxyTracerProvider = new ProxyTracerProvider();
|
|
10576
10884
|
};
|
|
10577
10885
|
return TraceAPI2;
|
|
@@ -10737,6 +11045,11 @@ function validateConcurrency(concurrency) {
|
|
|
10737
11045
|
throw new TypeError("Expected `concurrency` to be a number from 1 and up");
|
|
10738
11046
|
}
|
|
10739
11047
|
}
|
|
11048
|
+
var CronSchema = z.object({
|
|
11049
|
+
cron: z.string(),
|
|
11050
|
+
lastTimestamp: z.number().optional(),
|
|
11051
|
+
timestamp: z.number()
|
|
11052
|
+
});
|
|
10740
11053
|
var defaultRetrySettings = {
|
|
10741
11054
|
maxAttempts: 12,
|
|
10742
11055
|
factor: 2,
|
|
@@ -10751,6 +11064,7 @@ var Worker = class _Worker {
|
|
|
10751
11064
|
this.options = options;
|
|
10752
11065
|
this.logger = options.logger ?? new Logger("Worker", "debug");
|
|
10753
11066
|
this.tracer = options.tracer ?? trace.getTracer(options.name);
|
|
11067
|
+
this.meter = options.meter ?? metrics.getMeter(options.name);
|
|
10754
11068
|
this.shutdownTimeoutMs = options.shutdownTimeoutMs ?? 6e4;
|
|
10755
11069
|
const schema = Object.fromEntries(
|
|
10756
11070
|
Object.entries(this.options.catalog).map(([key, value]) => [key, value.schema])
|
|
@@ -10764,57 +11078,47 @@ var Worker = class _Worker {
|
|
|
10764
11078
|
this.jobs = options.jobs;
|
|
10765
11079
|
const { workers = 1, tasksPerWorker = 1, limit = 10 } = options.concurrency ?? {};
|
|
10766
11080
|
this.concurrency = { workers, tasksPerWorker, limit };
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
}
|
|
10772
|
-
this.metrics.enqueueDuration = new Histogram({
|
|
10773
|
-
name: "redis_worker_enqueue_duration_seconds",
|
|
10774
|
-
help: "The duration of enqueue operations",
|
|
10775
|
-
labelNames: ["worker_name", "job_type", "has_available_at"],
|
|
10776
|
-
buckets: [1e-3, 5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1],
|
|
10777
|
-
registers: [this.metrics.register]
|
|
10778
|
-
});
|
|
10779
|
-
this.metrics.dequeueDuration = new Histogram({
|
|
10780
|
-
name: "redis_worker_dequeue_duration_seconds",
|
|
10781
|
-
help: "The duration of dequeue operations",
|
|
10782
|
-
labelNames: ["worker_name", "worker_id", "task_count"],
|
|
10783
|
-
buckets: [1e-3, 5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1],
|
|
10784
|
-
registers: [this.metrics.register]
|
|
10785
|
-
});
|
|
10786
|
-
this.metrics.jobDuration = new Histogram({
|
|
10787
|
-
name: "redis_worker_job_duration_seconds",
|
|
10788
|
-
help: "The duration of job operations",
|
|
10789
|
-
labelNames: ["worker_name", "worker_id", "batch_size", "job_type", "attempt"],
|
|
10790
|
-
// use different buckets here as jobs can take a while to run
|
|
10791
|
-
buckets: [0.1, 0.25, 0.5, 1, 2.5, 5, 10, 20, 30, 45, 60],
|
|
10792
|
-
registers: [this.metrics.register]
|
|
10793
|
-
});
|
|
10794
|
-
this.metrics.ackDuration = new Histogram({
|
|
10795
|
-
name: "redis_worker_ack_duration_seconds",
|
|
10796
|
-
help: "The duration of ack operations",
|
|
10797
|
-
labelNames: ["worker_name"],
|
|
10798
|
-
buckets: [1e-3, 5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1],
|
|
10799
|
-
registers: [this.metrics.register]
|
|
10800
|
-
});
|
|
10801
|
-
this.metrics.redriveDuration = new Histogram({
|
|
10802
|
-
name: "redis_worker_redrive_duration_seconds",
|
|
10803
|
-
help: "The duration of redrive operations",
|
|
10804
|
-
labelNames: ["worker_name"],
|
|
10805
|
-
buckets: [1e-3, 5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1],
|
|
10806
|
-
registers: [this.metrics.register]
|
|
10807
|
-
});
|
|
10808
|
-
this.metrics.rescheduleDuration = new Histogram({
|
|
10809
|
-
name: "redis_worker_reschedule_duration_seconds",
|
|
10810
|
-
help: "The duration of reschedule operations",
|
|
10811
|
-
labelNames: ["worker_name"],
|
|
10812
|
-
buckets: [1e-3, 5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1],
|
|
10813
|
-
registers: [this.metrics.register]
|
|
11081
|
+
const masterQueueObservableGauge = this.meter.createObservableGauge("redis_worker.queue.size", {
|
|
11082
|
+
description: "The number of items in the queue",
|
|
11083
|
+
unit: "items",
|
|
11084
|
+
valueType: ValueType.INT
|
|
10814
11085
|
});
|
|
11086
|
+
masterQueueObservableGauge.addCallback(this.#updateQueueSizeMetric.bind(this));
|
|
11087
|
+
const deadLetterQueueObservableGauge = this.meter.createObservableGauge(
|
|
11088
|
+
"redis_worker.queue.dead_letter_size",
|
|
11089
|
+
{
|
|
11090
|
+
description: "The number of items in the dead letter queue",
|
|
11091
|
+
unit: "items",
|
|
11092
|
+
valueType: ValueType.INT
|
|
11093
|
+
}
|
|
11094
|
+
);
|
|
11095
|
+
deadLetterQueueObservableGauge.addCallback(this.#updateDeadLetterQueueSizeMetric.bind(this));
|
|
11096
|
+
const concurrencyLimitActiveObservableGauge = this.meter.createObservableGauge(
|
|
11097
|
+
"redis_worker.concurrency.active",
|
|
11098
|
+
{
|
|
11099
|
+
description: "The number of active workers",
|
|
11100
|
+
unit: "workers",
|
|
11101
|
+
valueType: ValueType.INT
|
|
11102
|
+
}
|
|
11103
|
+
);
|
|
11104
|
+
concurrencyLimitActiveObservableGauge.addCallback(
|
|
11105
|
+
this.#updateConcurrencyLimitActiveMetric.bind(this)
|
|
11106
|
+
);
|
|
11107
|
+
const concurrencyLimitPendingObservableGauge = this.meter.createObservableGauge(
|
|
11108
|
+
"redis_worker.concurrency.pending",
|
|
11109
|
+
{
|
|
11110
|
+
description: "The number of pending workers",
|
|
11111
|
+
unit: "workers",
|
|
11112
|
+
valueType: ValueType.INT
|
|
11113
|
+
}
|
|
11114
|
+
);
|
|
11115
|
+
concurrencyLimitPendingObservableGauge.addCallback(
|
|
11116
|
+
this.#updateConcurrencyLimitPendingMetric.bind(this)
|
|
11117
|
+
);
|
|
10815
11118
|
}
|
|
10816
11119
|
subscriber;
|
|
10817
11120
|
tracer;
|
|
11121
|
+
meter;
|
|
10818
11122
|
metrics = {};
|
|
10819
11123
|
queue;
|
|
10820
11124
|
jobs;
|
|
@@ -10824,11 +11128,44 @@ var Worker = class _Worker {
|
|
|
10824
11128
|
concurrency;
|
|
10825
11129
|
shutdownTimeoutMs;
|
|
10826
11130
|
// The p-limit limiter to control overall concurrency.
|
|
10827
|
-
|
|
11131
|
+
limiters = {};
|
|
11132
|
+
async #updateQueueSizeMetric(observableResult) {
|
|
11133
|
+
const queueSize = await this.queue.size();
|
|
11134
|
+
observableResult.observe(queueSize, {
|
|
11135
|
+
worker_name: this.options.name
|
|
11136
|
+
});
|
|
11137
|
+
}
|
|
11138
|
+
async #updateDeadLetterQueueSizeMetric(observableResult) {
|
|
11139
|
+
const deadLetterQueueSize = await this.queue.sizeOfDeadLetterQueue();
|
|
11140
|
+
observableResult.observe(deadLetterQueueSize, {
|
|
11141
|
+
worker_name: this.options.name
|
|
11142
|
+
});
|
|
11143
|
+
}
|
|
11144
|
+
async #updateConcurrencyLimitActiveMetric(observableResult) {
|
|
11145
|
+
for (const [workerId, limiter] of Object.entries(this.limiters)) {
|
|
11146
|
+
observableResult.observe(limiter.activeCount, {
|
|
11147
|
+
worker_name: this.options.name,
|
|
11148
|
+
worker_id: workerId
|
|
11149
|
+
});
|
|
11150
|
+
}
|
|
11151
|
+
}
|
|
11152
|
+
async #updateConcurrencyLimitPendingMetric(observableResult) {
|
|
11153
|
+
for (const [workerId, limiter] of Object.entries(this.limiters)) {
|
|
11154
|
+
observableResult.observe(limiter.pendingCount, {
|
|
11155
|
+
worker_name: this.options.name,
|
|
11156
|
+
worker_id: workerId
|
|
11157
|
+
});
|
|
11158
|
+
}
|
|
11159
|
+
}
|
|
10828
11160
|
start() {
|
|
10829
11161
|
const { workers, tasksPerWorker } = this.concurrency;
|
|
11162
|
+
this.logger.info("Starting worker", {
|
|
11163
|
+
workers,
|
|
11164
|
+
tasksPerWorker,
|
|
11165
|
+
concurrency: this.concurrency
|
|
11166
|
+
});
|
|
10830
11167
|
for (let i = 0; i < workers; i++) {
|
|
10831
|
-
this.workerLoops.push(this.runWorkerLoop(`worker-${nanoid(12)}`, tasksPerWorker));
|
|
11168
|
+
this.workerLoops.push(this.runWorkerLoop(`worker-${nanoid(12)}`, tasksPerWorker, i, workers));
|
|
10832
11169
|
}
|
|
10833
11170
|
this.setupShutdownHandlers();
|
|
10834
11171
|
this.subscriber = createRedisClient(this.options.redisOptions, {
|
|
@@ -10840,6 +11177,7 @@ var Worker = class _Worker {
|
|
|
10840
11177
|
}
|
|
10841
11178
|
});
|
|
10842
11179
|
this.setupSubscriber();
|
|
11180
|
+
this.setupCron();
|
|
10843
11181
|
return this;
|
|
10844
11182
|
}
|
|
10845
11183
|
/**
|
|
@@ -10892,6 +11230,56 @@ var Worker = class _Worker {
|
|
|
10892
11230
|
}
|
|
10893
11231
|
);
|
|
10894
11232
|
}
|
|
11233
|
+
/**
|
|
11234
|
+
* Enqueues a job for processing once. If the job is already in the queue, it will be ignored.
|
|
11235
|
+
* @param options - The enqueue options.
|
|
11236
|
+
* @param options.id - Required unique identifier for the job.
|
|
11237
|
+
* @param options.job - The job type from the worker catalog.
|
|
11238
|
+
* @param options.payload - The job payload that matches the schema defined in the catalog.
|
|
11239
|
+
* @param options.visibilityTimeoutMs - Optional visibility timeout in milliseconds. Defaults to value from catalog.
|
|
11240
|
+
* @param options.availableAt - Optional date when the job should become available for processing. Defaults to now.
|
|
11241
|
+
* @returns A promise that resolves when the job is enqueued.
|
|
11242
|
+
*/
|
|
11243
|
+
enqueueOnce({
|
|
11244
|
+
id,
|
|
11245
|
+
job,
|
|
11246
|
+
payload,
|
|
11247
|
+
visibilityTimeoutMs,
|
|
11248
|
+
availableAt
|
|
11249
|
+
}) {
|
|
11250
|
+
return startSpan(
|
|
11251
|
+
this.tracer,
|
|
11252
|
+
"enqueueOnce",
|
|
11253
|
+
async (span) => {
|
|
11254
|
+
const timeout = visibilityTimeoutMs ?? this.options.catalog[job]?.visibilityTimeoutMs;
|
|
11255
|
+
if (!timeout) {
|
|
11256
|
+
throw new Error(`No visibility timeout found for job ${String(job)} with id ${id}`);
|
|
11257
|
+
}
|
|
11258
|
+
span.setAttribute("job_visibility_timeout_ms", timeout);
|
|
11259
|
+
return this.withHistogram(
|
|
11260
|
+
this.metrics.enqueueDuration,
|
|
11261
|
+
this.queue.enqueueOnce({
|
|
11262
|
+
id,
|
|
11263
|
+
job,
|
|
11264
|
+
item: payload,
|
|
11265
|
+
visibilityTimeoutMs: timeout,
|
|
11266
|
+
availableAt
|
|
11267
|
+
}),
|
|
11268
|
+
{
|
|
11269
|
+
job_type: String(job),
|
|
11270
|
+
has_available_at: availableAt ? "true" : "false"
|
|
11271
|
+
}
|
|
11272
|
+
);
|
|
11273
|
+
},
|
|
11274
|
+
{
|
|
11275
|
+
kind: SpanKind.PRODUCER,
|
|
11276
|
+
attributes: {
|
|
11277
|
+
job_type: String(job),
|
|
11278
|
+
job_id: id
|
|
11279
|
+
}
|
|
11280
|
+
}
|
|
11281
|
+
);
|
|
11282
|
+
}
|
|
10895
11283
|
/**
|
|
10896
11284
|
* Reschedules an existing job to a new available date.
|
|
10897
11285
|
* If the job isn't in the queue, it will be ignored.
|
|
@@ -10928,37 +11316,78 @@ var Worker = class _Worker {
|
|
|
10928
11316
|
}
|
|
10929
11317
|
);
|
|
10930
11318
|
}
|
|
11319
|
+
async getJob(id) {
|
|
11320
|
+
return this.queue.getJob(id);
|
|
11321
|
+
}
|
|
10931
11322
|
/**
|
|
10932
11323
|
* The main loop that each worker runs. It repeatedly polls for items,
|
|
10933
11324
|
* processes them, and then waits before the next iteration.
|
|
10934
11325
|
*/
|
|
10935
|
-
async runWorkerLoop(workerId, taskCount) {
|
|
11326
|
+
async runWorkerLoop(workerId, taskCount, workerIndex, totalWorkers) {
|
|
11327
|
+
const limiter = pLimit(this.concurrency.limit);
|
|
11328
|
+
this.limiters[workerId] = limiter;
|
|
10936
11329
|
const pollIntervalMs = this.options.pollIntervalMs ?? 1e3;
|
|
10937
11330
|
const immediatePollIntervalMs = this.options.immediatePollIntervalMs ?? 100;
|
|
11331
|
+
const delayBetweenWorkers = this.options.pollIntervalMs ?? 1e3;
|
|
11332
|
+
const delay = delayBetweenWorkers * (totalWorkers - workerIndex);
|
|
11333
|
+
await _Worker.delay(delay);
|
|
11334
|
+
this.logger.info("Starting worker loop", {
|
|
11335
|
+
workerIndex,
|
|
11336
|
+
totalWorkers,
|
|
11337
|
+
delay,
|
|
11338
|
+
workerId,
|
|
11339
|
+
taskCount,
|
|
11340
|
+
pollIntervalMs,
|
|
11341
|
+
immediatePollIntervalMs,
|
|
11342
|
+
concurrencyOptions: this.concurrency
|
|
11343
|
+
});
|
|
10938
11344
|
while (!this.isShuttingDown) {
|
|
10939
|
-
if (
|
|
11345
|
+
if (limiter.activeCount + limiter.pendingCount >= this.concurrency.limit) {
|
|
11346
|
+
this.logger.debug("Worker at capacity, waiting", {
|
|
11347
|
+
workerId,
|
|
11348
|
+
concurrencyOptions: this.concurrency,
|
|
11349
|
+
activeCount: limiter.activeCount,
|
|
11350
|
+
pendingCount: limiter.pendingCount
|
|
11351
|
+
});
|
|
10940
11352
|
await _Worker.delay(pollIntervalMs);
|
|
10941
11353
|
continue;
|
|
10942
11354
|
}
|
|
11355
|
+
const $taskCount = Math.min(
|
|
11356
|
+
taskCount,
|
|
11357
|
+
this.concurrency.limit - limiter.activeCount - limiter.pendingCount
|
|
11358
|
+
);
|
|
10943
11359
|
try {
|
|
10944
11360
|
const items = await this.withHistogram(
|
|
10945
11361
|
this.metrics.dequeueDuration,
|
|
10946
|
-
this.queue.dequeue(taskCount),
|
|
11362
|
+
this.queue.dequeue($taskCount),
|
|
10947
11363
|
{
|
|
10948
11364
|
worker_id: workerId,
|
|
10949
|
-
task_count: taskCount
|
|
11365
|
+
task_count: $taskCount
|
|
10950
11366
|
}
|
|
10951
11367
|
);
|
|
10952
11368
|
if (items.length === 0) {
|
|
11369
|
+
this.logger.debug("No items to dequeue", {
|
|
11370
|
+
workerId,
|
|
11371
|
+
concurrencyOptions: this.concurrency,
|
|
11372
|
+
activeCount: limiter.activeCount,
|
|
11373
|
+
pendingCount: limiter.pendingCount
|
|
11374
|
+
});
|
|
10953
11375
|
await _Worker.delay(pollIntervalMs);
|
|
10954
11376
|
continue;
|
|
10955
11377
|
}
|
|
11378
|
+
this.logger.debug("Dequeued items", {
|
|
11379
|
+
workerId,
|
|
11380
|
+
itemCount: items.length,
|
|
11381
|
+
concurrencyOptions: this.concurrency,
|
|
11382
|
+
activeCount: limiter.activeCount,
|
|
11383
|
+
pendingCount: limiter.pendingCount
|
|
11384
|
+
});
|
|
10956
11385
|
for (const item of items) {
|
|
10957
|
-
|
|
10958
|
-
(
|
|
10959
|
-
|
|
10960
|
-
}
|
|
10961
|
-
);
|
|
11386
|
+
limiter(
|
|
11387
|
+
() => this.processItem(item, items.length, workerId, limiter)
|
|
11388
|
+
).catch((err) => {
|
|
11389
|
+
this.logger.error("Unhandled error in processItem:", { error: err, workerId, item });
|
|
11390
|
+
});
|
|
10962
11391
|
}
|
|
10963
11392
|
} catch (error) {
|
|
10964
11393
|
this.logger.error("Error dequeuing items:", { name: this.options.name, error });
|
|
@@ -10967,17 +11396,22 @@ var Worker = class _Worker {
|
|
|
10967
11396
|
}
|
|
10968
11397
|
await _Worker.delay(immediatePollIntervalMs);
|
|
10969
11398
|
}
|
|
11399
|
+
this.logger.info("Worker loop finished", { workerId });
|
|
10970
11400
|
}
|
|
10971
11401
|
/**
|
|
10972
11402
|
* Processes a single item.
|
|
10973
11403
|
*/
|
|
10974
|
-
async processItem({ id, job, item, visibilityTimeoutMs, attempt, timestamp, deduplicationKey }, batchSize, workerId) {
|
|
11404
|
+
async processItem({ id, job, item, visibilityTimeoutMs, attempt, timestamp, deduplicationKey }, batchSize, workerId, limiter) {
|
|
10975
11405
|
const catalogItem = this.options.catalog[job];
|
|
10976
11406
|
const handler = this.jobs[job];
|
|
10977
11407
|
if (!handler) {
|
|
10978
11408
|
this.logger.error(`No handler found for job type: ${job}`);
|
|
10979
11409
|
return;
|
|
10980
11410
|
}
|
|
11411
|
+
if (!catalogItem) {
|
|
11412
|
+
this.logger.error(`No catalog item found for job type: ${job}`);
|
|
11413
|
+
return;
|
|
11414
|
+
}
|
|
10981
11415
|
await startSpan(
|
|
10982
11416
|
this.tracer,
|
|
10983
11417
|
"processItem",
|
|
@@ -10993,6 +11427,9 @@ var Worker = class _Worker {
|
|
|
10993
11427
|
}
|
|
10994
11428
|
);
|
|
10995
11429
|
await this.queue.ack(id, deduplicationKey);
|
|
11430
|
+
if (catalogItem.cron) {
|
|
11431
|
+
await this.rescheduleCronJob(job, catalogItem, item);
|
|
11432
|
+
}
|
|
10996
11433
|
},
|
|
10997
11434
|
{
|
|
10998
11435
|
kind: SpanKind.CONSUMER,
|
|
@@ -11003,9 +11440,9 @@ var Worker = class _Worker {
|
|
|
11003
11440
|
job_timestamp: timestamp.getTime(),
|
|
11004
11441
|
job_age_in_ms: Date.now() - timestamp.getTime(),
|
|
11005
11442
|
worker_id: workerId,
|
|
11006
|
-
worker_limit_concurrency:
|
|
11007
|
-
worker_limit_active:
|
|
11008
|
-
worker_limit_pending:
|
|
11443
|
+
worker_limit_concurrency: limiter.concurrency,
|
|
11444
|
+
worker_limit_active: limiter.activeCount,
|
|
11445
|
+
worker_limit_pending: limiter.pendingCount,
|
|
11009
11446
|
worker_name: this.options.name,
|
|
11010
11447
|
batch_size: batchSize
|
|
11011
11448
|
}
|
|
@@ -11039,6 +11476,9 @@ var Worker = class _Worker {
|
|
|
11039
11476
|
errorMessage
|
|
11040
11477
|
});
|
|
11041
11478
|
await this.queue.moveToDeadLetterQueue(id, errorMessage);
|
|
11479
|
+
if (catalogItem.cron) {
|
|
11480
|
+
await this.rescheduleCronJob(job, catalogItem, item);
|
|
11481
|
+
}
|
|
11042
11482
|
return;
|
|
11043
11483
|
}
|
|
11044
11484
|
const retryDate = new Date(Date.now() + retryDelay);
|
|
@@ -11076,20 +11516,108 @@ var Worker = class _Worker {
|
|
|
11076
11516
|
});
|
|
11077
11517
|
}
|
|
11078
11518
|
async withHistogram(histogram, promise, labels) {
|
|
11079
|
-
if (!histogram
|
|
11519
|
+
if (!histogram) {
|
|
11080
11520
|
return promise;
|
|
11081
11521
|
}
|
|
11082
|
-
const
|
|
11522
|
+
const start = Date.now();
|
|
11083
11523
|
try {
|
|
11084
11524
|
return await promise;
|
|
11085
11525
|
} finally {
|
|
11086
|
-
|
|
11526
|
+
const duration = (Date.now() - start) / 1e3;
|
|
11527
|
+
histogram.record(duration, { worker_name: this.options.name, ...labels });
|
|
11087
11528
|
}
|
|
11088
11529
|
}
|
|
11089
11530
|
// A simple helper to delay for a given number of milliseconds.
|
|
11090
11531
|
static delay(ms) {
|
|
11091
11532
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11092
11533
|
}
|
|
11534
|
+
setupCron() {
|
|
11535
|
+
const cronJobs = Object.entries(this.options.catalog).filter(([_, value]) => value.cron);
|
|
11536
|
+
if (cronJobs.length === 0) {
|
|
11537
|
+
return;
|
|
11538
|
+
}
|
|
11539
|
+
this.logger.info("Setting up cron jobs", {
|
|
11540
|
+
cronJobs: cronJobs.map(([job, value]) => ({
|
|
11541
|
+
job,
|
|
11542
|
+
cron: value.cron,
|
|
11543
|
+
jitterInMs: value.jitterInMs
|
|
11544
|
+
}))
|
|
11545
|
+
});
|
|
11546
|
+
const enqueuePromises = cronJobs.map(
|
|
11547
|
+
([job, value]) => this.enqueueCronJob(value.cron, job, value.jitterInMs)
|
|
11548
|
+
);
|
|
11549
|
+
Promise.allSettled(enqueuePromises).then((results) => {
|
|
11550
|
+
results.forEach((result) => {
|
|
11551
|
+
if (result.status === "fulfilled") {
|
|
11552
|
+
this.logger.info("Enqueued cron job", { result: result.value });
|
|
11553
|
+
} else {
|
|
11554
|
+
this.logger.error("Failed to enqueue cron job", { reason: result.reason });
|
|
11555
|
+
}
|
|
11556
|
+
});
|
|
11557
|
+
});
|
|
11558
|
+
}
|
|
11559
|
+
async enqueueCronJob(cron, job, jitter, lastTimestamp) {
|
|
11560
|
+
const scheduledAt = this.calculateNextScheduledAt(cron, lastTimestamp);
|
|
11561
|
+
const identifier = [job, this.timestampIdentifier(scheduledAt)].join(":");
|
|
11562
|
+
const appliedJitter = typeof jitter === "number" ? Math.random() * jitter - jitter / 2 : 0;
|
|
11563
|
+
const availableAt = new Date(scheduledAt.getTime() + appliedJitter);
|
|
11564
|
+
const enqueued = await this.enqueueOnce({
|
|
11565
|
+
id: identifier,
|
|
11566
|
+
job,
|
|
11567
|
+
payload: {
|
|
11568
|
+
timestamp: scheduledAt.getTime(),
|
|
11569
|
+
lastTimestamp: lastTimestamp?.getTime(),
|
|
11570
|
+
cron
|
|
11571
|
+
},
|
|
11572
|
+
availableAt
|
|
11573
|
+
});
|
|
11574
|
+
this.logger.info("Enqueued cron job", {
|
|
11575
|
+
identifier,
|
|
11576
|
+
cron,
|
|
11577
|
+
job,
|
|
11578
|
+
scheduledAt,
|
|
11579
|
+
enqueued,
|
|
11580
|
+
availableAt,
|
|
11581
|
+
appliedJitter,
|
|
11582
|
+
jitter
|
|
11583
|
+
});
|
|
11584
|
+
return {
|
|
11585
|
+
identifier,
|
|
11586
|
+
cron,
|
|
11587
|
+
job,
|
|
11588
|
+
scheduledAt,
|
|
11589
|
+
enqueued
|
|
11590
|
+
};
|
|
11591
|
+
}
|
|
11592
|
+
async rescheduleCronJob(job, catalogItem, item) {
|
|
11593
|
+
if (!catalogItem.cron) {
|
|
11594
|
+
return;
|
|
11595
|
+
}
|
|
11596
|
+
return this.enqueueCronJob(
|
|
11597
|
+
catalogItem.cron,
|
|
11598
|
+
job,
|
|
11599
|
+
catalogItem.jitterInMs,
|
|
11600
|
+
new Date(item.timestamp)
|
|
11601
|
+
);
|
|
11602
|
+
}
|
|
11603
|
+
calculateNextScheduledAt(cron, lastTimestamp) {
|
|
11604
|
+
const scheduledAt = parseExpression(cron, {
|
|
11605
|
+
currentDate: lastTimestamp
|
|
11606
|
+
}).next().toDate();
|
|
11607
|
+
if (scheduledAt < /* @__PURE__ */ new Date()) {
|
|
11608
|
+
return this.calculateNextScheduledAt(cron);
|
|
11609
|
+
}
|
|
11610
|
+
return scheduledAt;
|
|
11611
|
+
}
|
|
11612
|
+
timestampIdentifier(timestamp) {
|
|
11613
|
+
const year = timestamp.getUTCFullYear();
|
|
11614
|
+
const month = timestamp.getUTCMonth();
|
|
11615
|
+
const day = timestamp.getUTCDate();
|
|
11616
|
+
const hour = timestamp.getUTCHours();
|
|
11617
|
+
const minute = timestamp.getUTCMinutes();
|
|
11618
|
+
const second = timestamp.getUTCSeconds();
|
|
11619
|
+
return `${year}-${month}-${day}-${hour}-${minute}-${second}`;
|
|
11620
|
+
}
|
|
11093
11621
|
setupSubscriber() {
|
|
11094
11622
|
const channel = `${this.options.name}:redrive`;
|
|
11095
11623
|
this.subscriber?.subscribe(channel, (err) => {
|
|
@@ -11146,6 +11674,6 @@ var Worker = class _Worker {
|
|
|
11146
11674
|
}
|
|
11147
11675
|
};
|
|
11148
11676
|
|
|
11149
|
-
export { SimpleQueue, Worker };
|
|
11677
|
+
export { CronSchema, SimpleQueue, Worker };
|
|
11150
11678
|
//# sourceMappingURL=index.js.map
|
|
11151
11679
|
//# sourceMappingURL=index.js.map
|