bullmq 5.39.1 → 5.40.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/dist/cjs/classes/job-scheduler.js +44 -63
- package/dist/cjs/classes/job-scheduler.js.map +1 -1
- package/dist/cjs/classes/scripts.js +5 -37
- package/dist/cjs/classes/scripts.js.map +1 -1
- package/dist/cjs/classes/worker.js +1 -1
- package/dist/cjs/classes/worker.js.map +1 -1
- package/dist/cjs/commands/addJobScheduler-2.lua +88 -0
- package/dist/cjs/scripts/addJobScheduler-2.js +234 -0
- package/dist/cjs/scripts/addJobScheduler-2.js.map +1 -0
- package/dist/cjs/scripts/index.js +1 -1
- package/dist/cjs/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/classes/job-scheduler.d.ts +1 -1
- package/dist/esm/classes/job-scheduler.js +44 -63
- package/dist/esm/classes/job-scheduler.js.map +1 -1
- package/dist/esm/classes/scripts.d.ts +3 -3
- package/dist/esm/classes/scripts.js +5 -37
- package/dist/esm/classes/scripts.js.map +1 -1
- package/dist/esm/classes/worker.js +1 -1
- package/dist/esm/classes/worker.js.map +1 -1
- package/dist/esm/commands/addJobScheduler-2.lua +88 -0
- package/dist/esm/scripts/addJobScheduler-2.js +231 -0
- package/dist/esm/scripts/addJobScheduler-2.js.map +1 -0
- package/dist/esm/scripts/index.d.ts +1 -1
- package/dist/esm/scripts/index.js +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +1 -1
- package/dist/cjs/commands/addJobScheduler-6.lua +0 -125
- package/dist/cjs/scripts/addJobScheduler-6.js +0 -369
- package/dist/cjs/scripts/addJobScheduler-6.js.map +0 -1
- package/dist/esm/commands/addJobScheduler-6.lua +0 -125
- package/dist/esm/scripts/addJobScheduler-6.js +0 -366
- package/dist/esm/scripts/addJobScheduler-6.js.map +0 -1
- /package/dist/esm/scripts/{addJobScheduler-6.d.ts → addJobScheduler-2.d.ts} +0 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
--[[
|
2
|
+
Adds a job scheduler, i.e. a job factory that creates jobs based on a given schedule (repeat options).
|
3
|
+
|
4
|
+
Input:
|
5
|
+
KEYS[1] 'repeat' key
|
6
|
+
KEYS[2] 'delayed' key
|
7
|
+
|
8
|
+
ARGV[1] next milliseconds
|
9
|
+
ARGV[2] msgpacked options
|
10
|
+
[1] name
|
11
|
+
[2] tz?
|
12
|
+
[3] patten?
|
13
|
+
[4] endDate?
|
14
|
+
[5] every?
|
15
|
+
ARGV[3] jobs scheduler id
|
16
|
+
ARGV[4] Json stringified template data
|
17
|
+
ARGV[5] mspacked template opts
|
18
|
+
ARGV[6] prefix key
|
19
|
+
|
20
|
+
Output:
|
21
|
+
repeatableKey - OK
|
22
|
+
]] local rcall = redis.call
|
23
|
+
local repeatKey = KEYS[1]
|
24
|
+
local delayedKey = KEYS[2]
|
25
|
+
|
26
|
+
local nextMillis = ARGV[1]
|
27
|
+
local jobSchedulerId = ARGV[3]
|
28
|
+
local templateOpts = cmsgpack.unpack(ARGV[5])
|
29
|
+
local prefixKey = ARGV[6]
|
30
|
+
|
31
|
+
-- Includes
|
32
|
+
--- @include "includes/removeJob"
|
33
|
+
|
34
|
+
local function storeRepeatableJob(schedulerId, repeatKey, nextMillis, rawOpts, templateData, templateOpts)
|
35
|
+
rcall("ZADD", repeatKey, nextMillis, schedulerId)
|
36
|
+
local opts = cmsgpack.unpack(rawOpts)
|
37
|
+
|
38
|
+
local optionalValues = {}
|
39
|
+
if opts['tz'] then
|
40
|
+
table.insert(optionalValues, "tz")
|
41
|
+
table.insert(optionalValues, opts['tz'])
|
42
|
+
end
|
43
|
+
|
44
|
+
if opts['pattern'] then
|
45
|
+
table.insert(optionalValues, "pattern")
|
46
|
+
table.insert(optionalValues, opts['pattern'])
|
47
|
+
end
|
48
|
+
|
49
|
+
if opts['endDate'] then
|
50
|
+
table.insert(optionalValues, "endDate")
|
51
|
+
table.insert(optionalValues, opts['endDate'])
|
52
|
+
end
|
53
|
+
|
54
|
+
if opts['every'] then
|
55
|
+
table.insert(optionalValues, "every")
|
56
|
+
table.insert(optionalValues, opts['every'])
|
57
|
+
end
|
58
|
+
|
59
|
+
local jsonTemplateOpts = cjson.encode(templateOpts)
|
60
|
+
if jsonTemplateOpts and jsonTemplateOpts ~= '{}' then
|
61
|
+
table.insert(optionalValues, "opts")
|
62
|
+
table.insert(optionalValues, jsonTemplateOpts)
|
63
|
+
end
|
64
|
+
|
65
|
+
if templateData and templateData ~= '{}' then
|
66
|
+
table.insert(optionalValues, "data")
|
67
|
+
table.insert(optionalValues, templateData)
|
68
|
+
end
|
69
|
+
|
70
|
+
rcall("HMSET", repeatKey .. ":" .. schedulerId, "name", opts['name'], unpack(optionalValues))
|
71
|
+
end
|
72
|
+
|
73
|
+
-- If we are overriding a repeatable job we must delete the delayed job for
|
74
|
+
-- the next iteration.
|
75
|
+
local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
|
76
|
+
if prevMillis ~= false then
|
77
|
+
local delayedJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
|
78
|
+
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
79
|
+
local nextDelayedJobKey = repeatKey .. ":" .. jobSchedulerId .. ":" .. nextMillis
|
80
|
+
|
81
|
+
if rcall("ZSCORE", delayedKey, delayedJobId) ~= false and
|
82
|
+
(rcall("EXISTS", nextDelayedJobKey) ~= 1 or delayedJobId == nextDelayedJobId) then
|
83
|
+
removeJob(delayedJobId, true, prefixKey, true --[[remove debounce key]] )
|
84
|
+
rcall("ZREM", delayedKey, delayedJobId)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
return storeRepeatableJob(jobSchedulerId, repeatKey, nextMillis, ARGV[2], ARGV[4], templateOpts)
|
@@ -0,0 +1,234 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.addJobScheduler = void 0;
|
4
|
+
const content = `--[[
|
5
|
+
Adds a job scheduler, i.e. a job factory that creates jobs based on a given schedule (repeat options).
|
6
|
+
Input:
|
7
|
+
KEYS[1] 'repeat' key
|
8
|
+
KEYS[2] 'delayed' key
|
9
|
+
ARGV[1] next milliseconds
|
10
|
+
ARGV[2] msgpacked options
|
11
|
+
[1] name
|
12
|
+
[2] tz?
|
13
|
+
[3] patten?
|
14
|
+
[4] endDate?
|
15
|
+
[5] every?
|
16
|
+
ARGV[3] jobs scheduler id
|
17
|
+
ARGV[4] Json stringified template data
|
18
|
+
ARGV[5] mspacked template opts
|
19
|
+
ARGV[6] prefix key
|
20
|
+
Output:
|
21
|
+
repeatableKey - OK
|
22
|
+
]] local rcall = redis.call
|
23
|
+
local repeatKey = KEYS[1]
|
24
|
+
local delayedKey = KEYS[2]
|
25
|
+
local nextMillis = ARGV[1]
|
26
|
+
local jobSchedulerId = ARGV[3]
|
27
|
+
local templateOpts = cmsgpack.unpack(ARGV[5])
|
28
|
+
local prefixKey = ARGV[6]
|
29
|
+
-- Includes
|
30
|
+
--[[
|
31
|
+
Function to remove job.
|
32
|
+
]]
|
33
|
+
-- Includes
|
34
|
+
--[[
|
35
|
+
Function to remove deduplication key.
|
36
|
+
]]
|
37
|
+
local function removeDeduplicationKey(prefixKey, jobKey)
|
38
|
+
local deduplicationId = rcall("HGET", jobKey, "deid")
|
39
|
+
if deduplicationId then
|
40
|
+
local deduplicationKey = prefixKey .. "de:" .. deduplicationId
|
41
|
+
rcall("DEL", deduplicationKey)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
--[[
|
45
|
+
Function to remove job keys.
|
46
|
+
]]
|
47
|
+
local function removeJobKeys(jobKey)
|
48
|
+
return rcall("DEL", jobKey, jobKey .. ':logs',
|
49
|
+
jobKey .. ':dependencies', jobKey .. ':processed', jobKey .. ':failed')
|
50
|
+
end
|
51
|
+
--[[
|
52
|
+
Check if this job has a parent. If so we will just remove it from
|
53
|
+
the parent child list, but if it is the last child we should move the parent to "wait/paused"
|
54
|
+
which requires code from "moveToFinished"
|
55
|
+
]]
|
56
|
+
-- Includes
|
57
|
+
--[[
|
58
|
+
Function to add job in target list and add marker if needed.
|
59
|
+
]]
|
60
|
+
-- Includes
|
61
|
+
--[[
|
62
|
+
Add marker if needed when a job is available.
|
63
|
+
]]
|
64
|
+
local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
|
65
|
+
if not isPausedOrMaxed then
|
66
|
+
rcall("ZADD", markerKey, 0, "0")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
|
70
|
+
rcall(pushCmd, targetKey, jobId)
|
71
|
+
addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
|
72
|
+
end
|
73
|
+
--[[
|
74
|
+
Functions to destructure job key.
|
75
|
+
Just a bit of warning, these functions may be a bit slow and affect performance significantly.
|
76
|
+
]]
|
77
|
+
local getJobIdFromKey = function (jobKey)
|
78
|
+
return string.match(jobKey, ".*:(.*)")
|
79
|
+
end
|
80
|
+
local getJobKeyPrefix = function (jobKey, jobId)
|
81
|
+
return string.sub(jobKey, 0, #jobKey - #jobId)
|
82
|
+
end
|
83
|
+
--[[
|
84
|
+
Function to check for the meta.paused key to decide if we are paused or not
|
85
|
+
(since an empty list and !EXISTS are not really the same).
|
86
|
+
]]
|
87
|
+
local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
|
88
|
+
local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency")
|
89
|
+
if queueAttributes[1] then
|
90
|
+
return pausedKey, true
|
91
|
+
else
|
92
|
+
if queueAttributes[2] then
|
93
|
+
local activeCount = rcall("LLEN", activeKey)
|
94
|
+
if activeCount >= tonumber(queueAttributes[2]) then
|
95
|
+
return waitKey, true
|
96
|
+
else
|
97
|
+
return waitKey, false
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
return waitKey, false
|
102
|
+
end
|
103
|
+
local function moveParentToWait(parentPrefix, parentId, emitEvent)
|
104
|
+
local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
|
105
|
+
parentPrefix .. "wait", parentPrefix .. "paused")
|
106
|
+
addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
|
107
|
+
if emitEvent then
|
108
|
+
local parentEventStream = parentPrefix .. "events"
|
109
|
+
rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
|
113
|
+
if parentKey then
|
114
|
+
local parentDependenciesKey = parentKey .. ":dependencies"
|
115
|
+
local result = rcall("SREM", parentDependenciesKey, jobKey)
|
116
|
+
if result > 0 then
|
117
|
+
local pendingDependencies = rcall("SCARD", parentDependenciesKey)
|
118
|
+
if pendingDependencies == 0 then
|
119
|
+
local parentId = getJobIdFromKey(parentKey)
|
120
|
+
local parentPrefix = getJobKeyPrefix(parentKey, parentId)
|
121
|
+
local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
|
122
|
+
if numRemovedElements == 1 then
|
123
|
+
if hard then -- remove parent in same queue
|
124
|
+
if parentPrefix == baseKey then
|
125
|
+
removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
|
126
|
+
removeJobKeys(parentKey)
|
127
|
+
if debounceId then
|
128
|
+
rcall("DEL", parentPrefix .. "de:" .. debounceId)
|
129
|
+
end
|
130
|
+
else
|
131
|
+
moveParentToWait(parentPrefix, parentId)
|
132
|
+
end
|
133
|
+
else
|
134
|
+
moveParentToWait(parentPrefix, parentId, true)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
return true
|
139
|
+
end
|
140
|
+
else
|
141
|
+
local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
|
142
|
+
local missedParentKey = parentAttributes[1]
|
143
|
+
if( (type(missedParentKey) == "string") and missedParentKey ~= ""
|
144
|
+
and (rcall("EXISTS", missedParentKey) == 1)) then
|
145
|
+
local parentDependenciesKey = missedParentKey .. ":dependencies"
|
146
|
+
local result = rcall("SREM", parentDependenciesKey, jobKey)
|
147
|
+
if result > 0 then
|
148
|
+
local pendingDependencies = rcall("SCARD", parentDependenciesKey)
|
149
|
+
if pendingDependencies == 0 then
|
150
|
+
local parentId = getJobIdFromKey(missedParentKey)
|
151
|
+
local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
|
152
|
+
local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
|
153
|
+
if numRemovedElements == 1 then
|
154
|
+
if hard then
|
155
|
+
if parentPrefix == baseKey then
|
156
|
+
removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
|
157
|
+
removeJobKeys(missedParentKey)
|
158
|
+
if parentAttributes[2] then
|
159
|
+
rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
|
160
|
+
end
|
161
|
+
else
|
162
|
+
moveParentToWait(parentPrefix, parentId)
|
163
|
+
end
|
164
|
+
else
|
165
|
+
moveParentToWait(parentPrefix, parentId, true)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
return true
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
return false
|
174
|
+
end
|
175
|
+
local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
|
176
|
+
local jobKey = baseKey .. jobId
|
177
|
+
removeParentDependencyKey(jobKey, hard, nil, baseKey)
|
178
|
+
if shouldRemoveDeduplicationKey then
|
179
|
+
removeDeduplicationKey(baseKey, jobKey)
|
180
|
+
end
|
181
|
+
removeJobKeys(jobKey)
|
182
|
+
end
|
183
|
+
local function storeRepeatableJob(schedulerId, repeatKey, nextMillis, rawOpts, templateData, templateOpts)
|
184
|
+
rcall("ZADD", repeatKey, nextMillis, schedulerId)
|
185
|
+
local opts = cmsgpack.unpack(rawOpts)
|
186
|
+
local optionalValues = {}
|
187
|
+
if opts['tz'] then
|
188
|
+
table.insert(optionalValues, "tz")
|
189
|
+
table.insert(optionalValues, opts['tz'])
|
190
|
+
end
|
191
|
+
if opts['pattern'] then
|
192
|
+
table.insert(optionalValues, "pattern")
|
193
|
+
table.insert(optionalValues, opts['pattern'])
|
194
|
+
end
|
195
|
+
if opts['endDate'] then
|
196
|
+
table.insert(optionalValues, "endDate")
|
197
|
+
table.insert(optionalValues, opts['endDate'])
|
198
|
+
end
|
199
|
+
if opts['every'] then
|
200
|
+
table.insert(optionalValues, "every")
|
201
|
+
table.insert(optionalValues, opts['every'])
|
202
|
+
end
|
203
|
+
local jsonTemplateOpts = cjson.encode(templateOpts)
|
204
|
+
if jsonTemplateOpts and jsonTemplateOpts ~= '{}' then
|
205
|
+
table.insert(optionalValues, "opts")
|
206
|
+
table.insert(optionalValues, jsonTemplateOpts)
|
207
|
+
end
|
208
|
+
if templateData and templateData ~= '{}' then
|
209
|
+
table.insert(optionalValues, "data")
|
210
|
+
table.insert(optionalValues, templateData)
|
211
|
+
end
|
212
|
+
rcall("HMSET", repeatKey .. ":" .. schedulerId, "name", opts['name'], unpack(optionalValues))
|
213
|
+
end
|
214
|
+
-- If we are overriding a repeatable job we must delete the delayed job for
|
215
|
+
-- the next iteration.
|
216
|
+
local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
|
217
|
+
if prevMillis ~= false then
|
218
|
+
local delayedJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
|
219
|
+
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
220
|
+
local nextDelayedJobKey = repeatKey .. ":" .. jobSchedulerId .. ":" .. nextMillis
|
221
|
+
if rcall("ZSCORE", delayedKey, delayedJobId) ~= false and
|
222
|
+
(rcall("EXISTS", nextDelayedJobKey) ~= 1 or delayedJobId == nextDelayedJobId) then
|
223
|
+
removeJob(delayedJobId, true, prefixKey, true --[[remove debounce key]] )
|
224
|
+
rcall("ZREM", delayedKey, delayedJobId)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
return storeRepeatableJob(jobSchedulerId, repeatKey, nextMillis, ARGV[2], ARGV[4], templateOpts)
|
228
|
+
`;
|
229
|
+
exports.addJobScheduler = {
|
230
|
+
name: 'addJobScheduler',
|
231
|
+
content,
|
232
|
+
keys: 2,
|
233
|
+
};
|
234
|
+
//# sourceMappingURL=addJobScheduler-2.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"addJobScheduler-2.js","sourceRoot":"","sources":["../../../src/scripts/addJobScheduler-2.ts"],"names":[],"mappings":";;;AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgOf,CAAC;AACW,QAAA,eAAe,GAAG;IAC7B,IAAI,EAAE,iBAAiB;IACvB,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}
|
@@ -2,7 +2,7 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const tslib_1 = require("tslib");
|
4
4
|
tslib_1.__exportStar(require("./addDelayedJob-6"), exports);
|
5
|
-
tslib_1.__exportStar(require("./addJobScheduler-
|
5
|
+
tslib_1.__exportStar(require("./addJobScheduler-2"), exports);
|
6
6
|
tslib_1.__exportStar(require("./addLog-2"), exports);
|
7
7
|
tslib_1.__exportStar(require("./addParentJob-4"), exports);
|
8
8
|
tslib_1.__exportStar(require("./addPrioritizedJob-8"), exports);
|