bullmq 5.81.0 → 5.81.2
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/cjs/classes/flow-producer.js +1 -1
- package/dist/cjs/classes/job.js +7 -6
- package/dist/cjs/classes/queue-base.js +1 -1
- package/dist/cjs/classes/queue-getters.js +7 -2
- package/dist/cjs/classes/scripts.js +33 -0
- package/dist/cjs/classes/worker.js +1 -1
- package/dist/cjs/commands/getJobs-1.lua +151 -0
- package/dist/cjs/enums/telemetry-attributes.js +4 -0
- package/dist/cjs/scripts/getJobs-1.js +142 -0
- package/dist/cjs/scripts/index.js +1 -0
- package/dist/cjs/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/cjs/utils/index.js +18 -0
- package/dist/cjs/version.js +1 -1
- package/dist/esm/classes/flow-producer.js +2 -2
- package/dist/esm/classes/job.d.ts +1 -1
- package/dist/esm/classes/job.js +7 -6
- package/dist/esm/classes/queue-base.js +2 -2
- package/dist/esm/classes/queue-getters.js +8 -3
- package/dist/esm/classes/scripts.d.ts +8 -0
- package/dist/esm/classes/scripts.js +33 -0
- package/dist/esm/classes/worker.js +2 -2
- package/dist/esm/commands/getJobs-1.lua +151 -0
- package/dist/esm/enums/telemetry-attributes.d.ts +5 -1
- package/dist/esm/enums/telemetry-attributes.js +4 -0
- package/dist/esm/scripts/getJobs-1.d.ts +5 -0
- package/dist/esm/scripts/getJobs-1.js +139 -0
- package/dist/esm/scripts/index.d.ts +1 -0
- package/dist/esm/scripts/index.js +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils/index.d.ts +12 -0
- package/dist/esm/utils/index.js +17 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +1 -1
|
@@ -34,7 +34,7 @@ class FlowProducer extends events_1.EventEmitter {
|
|
|
34
34
|
skipVersionCheck: opts.skipVersionCheck,
|
|
35
35
|
skipWaitingForReady: opts.skipWaitingForReady,
|
|
36
36
|
});
|
|
37
|
-
|
|
37
|
+
(0, utils_1.forwardConnectionError)(this, this.connection);
|
|
38
38
|
this.connection.on('close', () => {
|
|
39
39
|
this.queues.clear();
|
|
40
40
|
if (!this.closing) {
|
package/dist/cjs/classes/job.js
CHANGED
|
@@ -593,9 +593,9 @@ class Job {
|
|
|
593
593
|
/**
|
|
594
594
|
* Records job metrics if a meter is configured in telemetry options.
|
|
595
595
|
*
|
|
596
|
-
* @param
|
|
596
|
+
* @param state - The job state
|
|
597
597
|
*/
|
|
598
|
-
recordJobMetrics(
|
|
598
|
+
recordJobMetrics(state) {
|
|
599
599
|
var _a, _b;
|
|
600
600
|
const meter = (_b = (_a = this.queue.opts) === null || _a === void 0 ? void 0 : _a.telemetry) === null || _b === void 0 ? void 0 : _b.meter;
|
|
601
601
|
if (!meter) {
|
|
@@ -604,9 +604,10 @@ class Job {
|
|
|
604
604
|
const attributes = {
|
|
605
605
|
[enums_1.TelemetryAttributes.QueueName]: this.queue.name,
|
|
606
606
|
[enums_1.TelemetryAttributes.JobName]: this.name,
|
|
607
|
-
[enums_1.TelemetryAttributes.JobStatus]:
|
|
607
|
+
[enums_1.TelemetryAttributes.JobStatus]: state,
|
|
608
|
+
[enums_1.TelemetryAttributes.JobState]: state,
|
|
608
609
|
};
|
|
609
|
-
// Record counter metric based on
|
|
610
|
+
// Record counter metric based on state
|
|
610
611
|
const statusToCounterName = {
|
|
611
612
|
completed: enums_1.MetricNames.JobsCompleted,
|
|
612
613
|
failed: enums_1.MetricNames.JobsFailed,
|
|
@@ -615,9 +616,9 @@ class Job {
|
|
|
615
616
|
waiting: enums_1.MetricNames.JobsWaiting,
|
|
616
617
|
'waiting-children': enums_1.MetricNames.JobsWaitingChildren,
|
|
617
618
|
};
|
|
618
|
-
const counterName = statusToCounterName[
|
|
619
|
+
const counterName = statusToCounterName[state];
|
|
619
620
|
const counter = meter.createCounter(counterName, {
|
|
620
|
-
description: `Number of jobs ${
|
|
621
|
+
description: `Number of jobs ${state}`,
|
|
621
622
|
unit: '1',
|
|
622
623
|
});
|
|
623
624
|
counter.add(1, attributes);
|
|
@@ -40,7 +40,7 @@ class QueueBase extends events_1.EventEmitter {
|
|
|
40
40
|
skipVersionCheck: opts.skipVersionCheck,
|
|
41
41
|
skipWaitingForReady: opts.skipWaitingForReady,
|
|
42
42
|
});
|
|
43
|
-
|
|
43
|
+
(0, utils_1.forwardConnectionError)(this, this.connection);
|
|
44
44
|
this.connection.on('close', () => {
|
|
45
45
|
if (!this.closing) {
|
|
46
46
|
this.emit('ioredis:close');
|
|
@@ -389,8 +389,13 @@ class QueueGetters extends queue_base_1.QueueBase {
|
|
|
389
389
|
*/
|
|
390
390
|
async getJobs(types, start = 0, end = -1, asc = false) {
|
|
391
391
|
const currentTypes = this.sanitizeJobTypes(types);
|
|
392
|
-
const
|
|
393
|
-
return
|
|
392
|
+
const jobDataByType = await this.scripts.getJobs(currentTypes, start, end, asc);
|
|
393
|
+
return jobDataByType.reduce((jobs, jobData) => {
|
|
394
|
+
for (const [jobId, jobHashFields] of jobData || []) {
|
|
395
|
+
jobs.push(this.Job.fromJSON(this, (0, utils_1.array2obj)(jobHashFields), jobId));
|
|
396
|
+
}
|
|
397
|
+
return jobs;
|
|
398
|
+
}, []);
|
|
394
399
|
}
|
|
395
400
|
/**
|
|
396
401
|
* Returns the logs for a given Job.
|
|
@@ -15,6 +15,13 @@ const enums_1 = require("../enums");
|
|
|
15
15
|
const utils_1 = require("../utils");
|
|
16
16
|
const version_1 = require("../version");
|
|
17
17
|
const errors_1 = require("./errors");
|
|
18
|
+
/**
|
|
19
|
+
* Upper bound on the number of forward backfill iterations the `getJobs` Lua
|
|
20
|
+
* script performs to replace skipped ids (missing job hashes) within a bounded
|
|
21
|
+
* range. It caps the work done per call so a range full of missing jobs cannot
|
|
22
|
+
* scan the whole state unboundedly.
|
|
23
|
+
*/
|
|
24
|
+
const GET_JOBS_MAX_BACKFILL_ITERATIONS = 5;
|
|
18
25
|
class Scripts {
|
|
19
26
|
constructor(queue) {
|
|
20
27
|
this.queue = queue;
|
|
@@ -612,6 +619,32 @@ class Scripts {
|
|
|
612
619
|
const args = this.getRangesArgs(types, start, end, asc);
|
|
613
620
|
return await this.execCommand(client, 'getRanges', args);
|
|
614
621
|
}
|
|
622
|
+
getJobsArgs(types, start, end, asc) {
|
|
623
|
+
const queueKeys = this.queue.keys;
|
|
624
|
+
const transformedTypes = [
|
|
625
|
+
...new Set(types.map(type => (type === 'waiting' ? 'wait' : type))),
|
|
626
|
+
];
|
|
627
|
+
const keys = [queueKeys['']];
|
|
628
|
+
const args = [
|
|
629
|
+
start,
|
|
630
|
+
end,
|
|
631
|
+
asc ? '1' : '0',
|
|
632
|
+
GET_JOBS_MAX_BACKFILL_ITERATIONS,
|
|
633
|
+
...transformedTypes,
|
|
634
|
+
];
|
|
635
|
+
return keys.concat(args);
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Fetches job ids and their job hashes for the provided states in a single
|
|
639
|
+
* script, skipping ids whose job hash is missing (for example the deprecated
|
|
640
|
+
* wait list marker or jobs removed after their id was read). Each returned
|
|
641
|
+
* entry is a `[jobId, jobHashFields]` tuple grouped per requested type.
|
|
642
|
+
*/
|
|
643
|
+
async getJobs(types, start = 0, end = -1, asc = false) {
|
|
644
|
+
const client = await this.queue.client;
|
|
645
|
+
const args = this.getJobsArgs(types, start, end, asc);
|
|
646
|
+
return await this.execCommand(client, 'getJobs', args);
|
|
647
|
+
}
|
|
615
648
|
getCountsArgs(types) {
|
|
616
649
|
const queueKeys = this.queue.keys;
|
|
617
650
|
const transformedTypes = types.map(type => {
|
|
@@ -126,7 +126,7 @@ class Worker extends queue_base_1.QueueBase {
|
|
|
126
126
|
blocking: true,
|
|
127
127
|
skipVersionCheck: opts.skipVersionCheck,
|
|
128
128
|
});
|
|
129
|
-
|
|
129
|
+
(0, utils_1.forwardConnectionError)(this, this.blockingConnection);
|
|
130
130
|
this.blockingConnection.on('ready', () => setTimeout(() => this.emit('ready'), 0));
|
|
131
131
|
}
|
|
132
132
|
/**
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
--[[
|
|
2
|
+
Get jobs (id + data) for the provided states.
|
|
3
|
+
|
|
4
|
+
Job ids and their hashes are read in the same script so that ids whose hash
|
|
5
|
+
disappears after the id is read (but before the job is loaded) do not appear
|
|
6
|
+
in the result set. Ids without a job hash (for example the deprecated wait
|
|
7
|
+
list marker entry stored in the list) are skipped. For bounded ranges the
|
|
8
|
+
script iterates forward using the range offset as a cursor to backfill
|
|
9
|
+
skipped ids, preserving the requested page size when possible.
|
|
10
|
+
|
|
11
|
+
Input:
|
|
12
|
+
KEYS[1] 'prefix'
|
|
13
|
+
|
|
14
|
+
ARGV[1] start
|
|
15
|
+
ARGV[2] end
|
|
16
|
+
ARGV[3] asc ('1' | '0')
|
|
17
|
+
ARGV[4] max iterations (backfill bound)
|
|
18
|
+
ARGV[5...] types
|
|
19
|
+
|
|
20
|
+
Output:
|
|
21
|
+
results grouped per requested type; each entry is a
|
|
22
|
+
{jobId, {field, value, ...}} tuple
|
|
23
|
+
]]
|
|
24
|
+
local rcall = redis.call
|
|
25
|
+
local prefix = KEYS[1]
|
|
26
|
+
local rangeStart = tonumber(ARGV[1])
|
|
27
|
+
local rangeEnd = tonumber(ARGV[2])
|
|
28
|
+
local asc = ARGV[3] == "1"
|
|
29
|
+
local max_iterations = tonumber(ARGV[4])
|
|
30
|
+
local results = {}
|
|
31
|
+
|
|
32
|
+
local function isListType(stateType)
|
|
33
|
+
return stateType == "wait" or stateType == "paused" or stateType == "active"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
-- Fetch a slice of ids for the given state respecting the requested order.
|
|
37
|
+
local function fetchIds(stateKey, stateType, sliceStart, sliceEnd, listLength)
|
|
38
|
+
if isListType(stateType) then
|
|
39
|
+
if asc then
|
|
40
|
+
local modifiedRangeStart
|
|
41
|
+
local modifiedRangeEnd
|
|
42
|
+
if sliceStart == -1 then
|
|
43
|
+
modifiedRangeStart = 0
|
|
44
|
+
else
|
|
45
|
+
modifiedRangeStart = -(sliceStart + 1)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if sliceEnd == -1 then
|
|
49
|
+
modifiedRangeEnd = 0
|
|
50
|
+
else
|
|
51
|
+
modifiedRangeEnd = -(sliceEnd + 1)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
-- Ascending list slices use negative indexes. When the whole window is
|
|
55
|
+
-- beyond the list length Redis clamps both indexes to 0 and LRANGE would
|
|
56
|
+
-- return the head element, so guard against out-of-range slices with LLEN.
|
|
57
|
+
if listLength ~= nil and sliceStart >= 0 and sliceEnd >= 0 and sliceStart >= listLength then
|
|
58
|
+
return {}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
local ids = rcall("LRANGE", stateKey, modifiedRangeEnd, modifiedRangeStart)
|
|
62
|
+
local reversed = {}
|
|
63
|
+
for i = #ids, 1, -1 do
|
|
64
|
+
reversed[#reversed + 1] = ids[i]
|
|
65
|
+
end
|
|
66
|
+
return reversed
|
|
67
|
+
else
|
|
68
|
+
return rcall("LRANGE", stateKey, sliceStart, sliceEnd)
|
|
69
|
+
end
|
|
70
|
+
else
|
|
71
|
+
if asc then
|
|
72
|
+
return rcall("ZRANGE", stateKey, sliceStart, sliceEnd)
|
|
73
|
+
else
|
|
74
|
+
return rcall("ZREVRANGE", stateKey, sliceStart, sliceEnd)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
-- Fetch the job hash for an id and append it when present.
|
|
80
|
+
local function appendJob(entries, jobId)
|
|
81
|
+
local jobData = rcall("HGETALL", prefix .. jobId)
|
|
82
|
+
if #jobData > 0 then
|
|
83
|
+
entries[#entries + 1] = {jobId, jobData}
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
local function cleanupDeprecatedMarker(stateKey, stateType)
|
|
88
|
+
if stateType == "wait" or stateType == "paused" then
|
|
89
|
+
local marker = rcall("LINDEX", stateKey, -1)
|
|
90
|
+
if marker and string.sub(marker, 1, 2) == "0:" then
|
|
91
|
+
local count = rcall("LLEN", stateKey)
|
|
92
|
+
if count > 1 then
|
|
93
|
+
rcall("RPOP", stateKey)
|
|
94
|
+
return count - 1
|
|
95
|
+
end
|
|
96
|
+
return 0
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
local function collectJobs(stateKey, stateType)
|
|
102
|
+
local entries = {}
|
|
103
|
+
local listLength
|
|
104
|
+
local cleanedListLength = cleanupDeprecatedMarker(stateKey, stateType)
|
|
105
|
+
|
|
106
|
+
if asc and isListType(stateType) and rangeStart >= 0 and rangeEnd >= 0 then
|
|
107
|
+
if cleanedListLength ~= nil then
|
|
108
|
+
listLength = cleanedListLength
|
|
109
|
+
else
|
|
110
|
+
listLength = rcall("LLEN", stateKey)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
-- Unbounded or negative ranges: fetch the exact window and skip missing ids.
|
|
115
|
+
if rangeStart < 0 or rangeEnd < 0 then
|
|
116
|
+
local ids = fetchIds(stateKey, stateType, rangeStart, rangeEnd, listLength)
|
|
117
|
+
for i = 1, #ids do
|
|
118
|
+
appendJob(entries, ids[i])
|
|
119
|
+
end
|
|
120
|
+
return entries
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
-- Bounded range: iterate forward to backfill skipped ids.
|
|
124
|
+
local needed = rangeEnd - rangeStart + 1
|
|
125
|
+
local cursor = rangeStart
|
|
126
|
+
local iterations = 0
|
|
127
|
+
while #entries < needed and iterations < max_iterations do
|
|
128
|
+
local ids = fetchIds(stateKey, stateType, cursor, cursor + needed - 1, listLength)
|
|
129
|
+
if #ids == 0 then
|
|
130
|
+
break
|
|
131
|
+
end
|
|
132
|
+
for i = 1, #ids do
|
|
133
|
+
if #entries >= needed then
|
|
134
|
+
break
|
|
135
|
+
end
|
|
136
|
+
appendJob(entries, ids[i])
|
|
137
|
+
end
|
|
138
|
+
cursor = cursor + #ids
|
|
139
|
+
iterations = iterations + 1
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
return entries
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
for i = 5, #ARGV do
|
|
146
|
+
local stateType = ARGV[i]
|
|
147
|
+
local stateKey = prefix .. stateType
|
|
148
|
+
results[#results + 1] = collectJobs(stateKey, stateType)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
return results
|
|
@@ -42,7 +42,11 @@ var TelemetryAttributes;
|
|
|
42
42
|
TelemetryAttributes["JobFailedReason"] = "bullmq.job.failed.reason";
|
|
43
43
|
TelemetryAttributes["FlowName"] = "bullmq.flow.name";
|
|
44
44
|
TelemetryAttributes["JobSchedulerId"] = "bullmq.job.scheduler.id";
|
|
45
|
+
/**
|
|
46
|
+
* @deprecated Use JobState instead. Will be removed in a future version.
|
|
47
|
+
*/
|
|
45
48
|
TelemetryAttributes["JobStatus"] = "bullmq.job.status";
|
|
49
|
+
TelemetryAttributes["JobState"] = "bullmq.job.state";
|
|
46
50
|
})(TelemetryAttributes || (exports.TelemetryAttributes = TelemetryAttributes = {}));
|
|
47
51
|
/**
|
|
48
52
|
* Standard metric names for BullMQ telemetry
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getJobs = void 0;
|
|
4
|
+
const content = `--[[
|
|
5
|
+
Get jobs (id + data) for the provided states.
|
|
6
|
+
Job ids and their hashes are read in the same script so that ids whose hash
|
|
7
|
+
disappears after the id is read (but before the job is loaded) do not appear
|
|
8
|
+
in the result set. Ids without a job hash (for example the deprecated wait
|
|
9
|
+
list marker entry stored in the list) are skipped. For bounded ranges the
|
|
10
|
+
script iterates forward using the range offset as a cursor to backfill
|
|
11
|
+
skipped ids, preserving the requested page size when possible.
|
|
12
|
+
Input:
|
|
13
|
+
KEYS[1] 'prefix'
|
|
14
|
+
ARGV[1] start
|
|
15
|
+
ARGV[2] end
|
|
16
|
+
ARGV[3] asc ('1' | '0')
|
|
17
|
+
ARGV[4] max iterations (backfill bound)
|
|
18
|
+
ARGV[5...] types
|
|
19
|
+
Output:
|
|
20
|
+
results grouped per requested type; each entry is a
|
|
21
|
+
{jobId, {field, value, ...}} tuple
|
|
22
|
+
]]
|
|
23
|
+
local rcall = redis.call
|
|
24
|
+
local prefix = KEYS[1]
|
|
25
|
+
local rangeStart = tonumber(ARGV[1])
|
|
26
|
+
local rangeEnd = tonumber(ARGV[2])
|
|
27
|
+
local asc = ARGV[3] == "1"
|
|
28
|
+
local max_iterations = tonumber(ARGV[4])
|
|
29
|
+
local results = {}
|
|
30
|
+
local function isListType(stateType)
|
|
31
|
+
return stateType == "wait" or stateType == "paused" or stateType == "active"
|
|
32
|
+
end
|
|
33
|
+
-- Fetch a slice of ids for the given state respecting the requested order.
|
|
34
|
+
local function fetchIds(stateKey, stateType, sliceStart, sliceEnd, listLength)
|
|
35
|
+
if isListType(stateType) then
|
|
36
|
+
if asc then
|
|
37
|
+
local modifiedRangeStart
|
|
38
|
+
local modifiedRangeEnd
|
|
39
|
+
if sliceStart == -1 then
|
|
40
|
+
modifiedRangeStart = 0
|
|
41
|
+
else
|
|
42
|
+
modifiedRangeStart = -(sliceStart + 1)
|
|
43
|
+
end
|
|
44
|
+
if sliceEnd == -1 then
|
|
45
|
+
modifiedRangeEnd = 0
|
|
46
|
+
else
|
|
47
|
+
modifiedRangeEnd = -(sliceEnd + 1)
|
|
48
|
+
end
|
|
49
|
+
-- Ascending list slices use negative indexes. When the whole window is
|
|
50
|
+
-- beyond the list length Redis clamps both indexes to 0 and LRANGE would
|
|
51
|
+
-- return the head element, so guard against out-of-range slices with LLEN.
|
|
52
|
+
if listLength ~= nil and sliceStart >= 0 and sliceEnd >= 0 and sliceStart >= listLength then
|
|
53
|
+
return {}
|
|
54
|
+
end
|
|
55
|
+
local ids = rcall("LRANGE", stateKey, modifiedRangeEnd, modifiedRangeStart)
|
|
56
|
+
local reversed = {}
|
|
57
|
+
for i = #ids, 1, -1 do
|
|
58
|
+
reversed[#reversed + 1] = ids[i]
|
|
59
|
+
end
|
|
60
|
+
return reversed
|
|
61
|
+
else
|
|
62
|
+
return rcall("LRANGE", stateKey, sliceStart, sliceEnd)
|
|
63
|
+
end
|
|
64
|
+
else
|
|
65
|
+
if asc then
|
|
66
|
+
return rcall("ZRANGE", stateKey, sliceStart, sliceEnd)
|
|
67
|
+
else
|
|
68
|
+
return rcall("ZREVRANGE", stateKey, sliceStart, sliceEnd)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
-- Fetch the job hash for an id and append it when present.
|
|
73
|
+
local function appendJob(entries, jobId)
|
|
74
|
+
local jobData = rcall("HGETALL", prefix .. jobId)
|
|
75
|
+
if #jobData > 0 then
|
|
76
|
+
entries[#entries + 1] = {jobId, jobData}
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
local function cleanupDeprecatedMarker(stateKey, stateType)
|
|
80
|
+
if stateType == "wait" or stateType == "paused" then
|
|
81
|
+
local marker = rcall("LINDEX", stateKey, -1)
|
|
82
|
+
if marker and string.sub(marker, 1, 2) == "0:" then
|
|
83
|
+
local count = rcall("LLEN", stateKey)
|
|
84
|
+
if count > 1 then
|
|
85
|
+
rcall("RPOP", stateKey)
|
|
86
|
+
return count - 1
|
|
87
|
+
end
|
|
88
|
+
return 0
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
local function collectJobs(stateKey, stateType)
|
|
93
|
+
local entries = {}
|
|
94
|
+
local listLength
|
|
95
|
+
local cleanedListLength = cleanupDeprecatedMarker(stateKey, stateType)
|
|
96
|
+
if asc and isListType(stateType) and rangeStart >= 0 and rangeEnd >= 0 then
|
|
97
|
+
if cleanedListLength ~= nil then
|
|
98
|
+
listLength = cleanedListLength
|
|
99
|
+
else
|
|
100
|
+
listLength = rcall("LLEN", stateKey)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
-- Unbounded or negative ranges: fetch the exact window and skip missing ids.
|
|
104
|
+
if rangeStart < 0 or rangeEnd < 0 then
|
|
105
|
+
local ids = fetchIds(stateKey, stateType, rangeStart, rangeEnd, listLength)
|
|
106
|
+
for i = 1, #ids do
|
|
107
|
+
appendJob(entries, ids[i])
|
|
108
|
+
end
|
|
109
|
+
return entries
|
|
110
|
+
end
|
|
111
|
+
-- Bounded range: iterate forward to backfill skipped ids.
|
|
112
|
+
local needed = rangeEnd - rangeStart + 1
|
|
113
|
+
local cursor = rangeStart
|
|
114
|
+
local iterations = 0
|
|
115
|
+
while #entries < needed and iterations < max_iterations do
|
|
116
|
+
local ids = fetchIds(stateKey, stateType, cursor, cursor + needed - 1, listLength)
|
|
117
|
+
if #ids == 0 then
|
|
118
|
+
break
|
|
119
|
+
end
|
|
120
|
+
for i = 1, #ids do
|
|
121
|
+
if #entries >= needed then
|
|
122
|
+
break
|
|
123
|
+
end
|
|
124
|
+
appendJob(entries, ids[i])
|
|
125
|
+
end
|
|
126
|
+
cursor = cursor + #ids
|
|
127
|
+
iterations = iterations + 1
|
|
128
|
+
end
|
|
129
|
+
return entries
|
|
130
|
+
end
|
|
131
|
+
for i = 5, #ARGV do
|
|
132
|
+
local stateType = ARGV[i]
|
|
133
|
+
local stateKey = prefix .. stateType
|
|
134
|
+
results[#results + 1] = collectJobs(stateKey, stateType)
|
|
135
|
+
end
|
|
136
|
+
return results
|
|
137
|
+
`;
|
|
138
|
+
exports.getJobs = {
|
|
139
|
+
name: 'getJobs',
|
|
140
|
+
content,
|
|
141
|
+
keys: 1,
|
|
142
|
+
};
|
|
@@ -18,6 +18,7 @@ tslib_1.__exportStar(require("./getCounts-1"), exports);
|
|
|
18
18
|
tslib_1.__exportStar(require("./getCountsPerPriority-4"), exports);
|
|
19
19
|
tslib_1.__exportStar(require("./getDependencyCounts-4"), exports);
|
|
20
20
|
tslib_1.__exportStar(require("./getJobScheduler-1"), exports);
|
|
21
|
+
tslib_1.__exportStar(require("./getJobs-1"), exports);
|
|
21
22
|
tslib_1.__exportStar(require("./getMetrics-2"), exports);
|
|
22
23
|
tslib_1.__exportStar(require("./getRanges-1"), exports);
|
|
23
24
|
tslib_1.__exportStar(require("./getRateLimitTtl-2"), exports);
|