bullmq 5.39.2 → 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/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/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
@@ -1,366 +0,0 @@
|
|
1
|
-
const content = `--[[
|
2
|
-
Adds a job scheduler, i.e. a job factory that creates jobs based on a given schedule (repeat options).
|
3
|
-
Input:
|
4
|
-
KEYS[1] 'marker',
|
5
|
-
KEYS[2] 'meta'
|
6
|
-
KEYS[3] 'id'
|
7
|
-
KEYS[4] 'delayed'
|
8
|
-
KEYS[5] events stream key
|
9
|
-
KEYS[6] 'repeat' key
|
10
|
-
ARGV[1] next milliseconds
|
11
|
-
ARGV[2] msgpacked options
|
12
|
-
[1] name
|
13
|
-
[2] tz?
|
14
|
-
[3] patten?
|
15
|
-
[4] endDate?
|
16
|
-
[5] every?
|
17
|
-
ARGV[3] jobs scheduler id
|
18
|
-
ARGV[4] Json stringified template data
|
19
|
-
ARGV[5] msgpacked template opts
|
20
|
-
ARGV[6] msgpacked delayed opts
|
21
|
-
ARGV[7] timestamp
|
22
|
-
ARGV[8] prefix key
|
23
|
-
ARGV[9] producer key
|
24
|
-
Output:
|
25
|
-
next delayed job id - OK
|
26
|
-
]]
|
27
|
-
local rcall = redis.call
|
28
|
-
local repeatKey = KEYS[6]
|
29
|
-
local delayedKey = KEYS[4]
|
30
|
-
local timestamp = ARGV[7]
|
31
|
-
local nextMillis = ARGV[1]
|
32
|
-
local jobSchedulerId = ARGV[3]
|
33
|
-
local templateOpts = cmsgpack.unpack(ARGV[5])
|
34
|
-
local prefixKey = ARGV[8]
|
35
|
-
-- Includes
|
36
|
-
--[[
|
37
|
-
Adds a delayed job to the queue by doing the following:
|
38
|
-
- Creates a new job key with the job data.
|
39
|
-
- adds to delayed zset.
|
40
|
-
- Emits a global event 'delayed' if the job is delayed.
|
41
|
-
]]
|
42
|
-
-- Includes
|
43
|
-
--[[
|
44
|
-
Add delay marker if needed.
|
45
|
-
]]
|
46
|
-
-- Includes
|
47
|
-
--[[
|
48
|
-
Function to return the next delayed job timestamp.
|
49
|
-
]]
|
50
|
-
local function getNextDelayedTimestamp(delayedKey)
|
51
|
-
local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
|
52
|
-
if #result then
|
53
|
-
local nextTimestamp = tonumber(result[2])
|
54
|
-
if nextTimestamp ~= nil then
|
55
|
-
return nextTimestamp / 0x1000
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
local function addDelayMarkerIfNeeded(markerKey, delayedKey)
|
60
|
-
local nextTimestamp = getNextDelayedTimestamp(delayedKey)
|
61
|
-
if nextTimestamp ~= nil then
|
62
|
-
-- Replace the score of the marker with the newest known
|
63
|
-
-- next timestamp.
|
64
|
-
rcall("ZADD", markerKey, nextTimestamp, "1")
|
65
|
-
end
|
66
|
-
end
|
67
|
-
--[[
|
68
|
-
Bake in the job id first 12 bits into the timestamp
|
69
|
-
to guarantee correct execution order of delayed jobs
|
70
|
-
(up to 4096 jobs per given timestamp or 4096 jobs apart per timestamp)
|
71
|
-
WARNING: Jobs that are so far apart that they wrap around will cause FIFO to fail
|
72
|
-
]]
|
73
|
-
local function getDelayedScore(delayedKey, timestamp, delay)
|
74
|
-
local delayedTimestamp = (delay > 0 and (tonumber(timestamp) + delay)) or tonumber(timestamp)
|
75
|
-
local minScore = delayedTimestamp * 0x1000
|
76
|
-
local maxScore = (delayedTimestamp + 1 ) * 0x1000 - 1
|
77
|
-
local result = rcall("ZREVRANGEBYSCORE", delayedKey, maxScore,
|
78
|
-
minScore, "WITHSCORES","LIMIT", 0, 1)
|
79
|
-
if #result then
|
80
|
-
local currentMaxScore = tonumber(result[2])
|
81
|
-
if currentMaxScore ~= nil then
|
82
|
-
if currentMaxScore >= maxScore then
|
83
|
-
return maxScore, delayedTimestamp
|
84
|
-
else
|
85
|
-
return currentMaxScore + 1, delayedTimestamp
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
return minScore, delayedTimestamp
|
90
|
-
end
|
91
|
-
--[[
|
92
|
-
Function to store a job
|
93
|
-
]]
|
94
|
-
local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
|
95
|
-
parentKey, parentData, repeatJobKey)
|
96
|
-
local jsonOpts = cjson.encode(opts)
|
97
|
-
local delay = opts['delay'] or 0
|
98
|
-
local priority = opts['priority'] or 0
|
99
|
-
local debounceId = opts['de'] and opts['de']['id']
|
100
|
-
local optionalValues = {}
|
101
|
-
if parentKey ~= nil then
|
102
|
-
table.insert(optionalValues, "parentKey")
|
103
|
-
table.insert(optionalValues, parentKey)
|
104
|
-
table.insert(optionalValues, "parent")
|
105
|
-
table.insert(optionalValues, parentData)
|
106
|
-
end
|
107
|
-
if repeatJobKey ~= nil then
|
108
|
-
table.insert(optionalValues, "rjk")
|
109
|
-
table.insert(optionalValues, repeatJobKey)
|
110
|
-
end
|
111
|
-
if debounceId then
|
112
|
-
table.insert(optionalValues, "deid")
|
113
|
-
table.insert(optionalValues, debounceId)
|
114
|
-
end
|
115
|
-
rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
|
116
|
-
"timestamp", timestamp, "delay", delay, "priority", priority,
|
117
|
-
unpack(optionalValues))
|
118
|
-
rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
|
119
|
-
return delay, priority
|
120
|
-
end
|
121
|
-
local function addDelayedJob(jobIdKey, jobId, delayedKey, eventsKey, name, data, opts, timestamp, repeatJobKey,
|
122
|
-
maxEvents, markerKey, parentKey, parentData)
|
123
|
-
-- Store the job.
|
124
|
-
local delay, priority = storeJob(eventsKey, jobIdKey, jobId, name, data,
|
125
|
-
opts, timestamp, parentKey, parentData, repeatJobKey)
|
126
|
-
local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
|
127
|
-
rcall("ZADD", delayedKey, score, jobId)
|
128
|
-
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
|
129
|
-
"jobId", jobId, "delay", delayedTimestamp)
|
130
|
-
-- mark that a delayed job is available
|
131
|
-
addDelayMarkerIfNeeded(markerKey, delayedKey)
|
132
|
-
end
|
133
|
-
--[[
|
134
|
-
Function to get max events value or set by default 10000.
|
135
|
-
]]
|
136
|
-
local function getOrSetMaxEvents(metaKey)
|
137
|
-
local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
|
138
|
-
if not maxEvents then
|
139
|
-
maxEvents = 10000
|
140
|
-
rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
|
141
|
-
end
|
142
|
-
return maxEvents
|
143
|
-
end
|
144
|
-
--[[
|
145
|
-
Function to remove job.
|
146
|
-
]]
|
147
|
-
-- Includes
|
148
|
-
--[[
|
149
|
-
Function to remove deduplication key.
|
150
|
-
]]
|
151
|
-
local function removeDeduplicationKey(prefixKey, jobKey)
|
152
|
-
local deduplicationId = rcall("HGET", jobKey, "deid")
|
153
|
-
if deduplicationId then
|
154
|
-
local deduplicationKey = prefixKey .. "de:" .. deduplicationId
|
155
|
-
rcall("DEL", deduplicationKey)
|
156
|
-
end
|
157
|
-
end
|
158
|
-
--[[
|
159
|
-
Function to remove job keys.
|
160
|
-
]]
|
161
|
-
local function removeJobKeys(jobKey)
|
162
|
-
return rcall("DEL", jobKey, jobKey .. ':logs',
|
163
|
-
jobKey .. ':dependencies', jobKey .. ':processed', jobKey .. ':failed')
|
164
|
-
end
|
165
|
-
--[[
|
166
|
-
Check if this job has a parent. If so we will just remove it from
|
167
|
-
the parent child list, but if it is the last child we should move the parent to "wait/paused"
|
168
|
-
which requires code from "moveToFinished"
|
169
|
-
]]
|
170
|
-
-- Includes
|
171
|
-
--[[
|
172
|
-
Function to add job in target list and add marker if needed.
|
173
|
-
]]
|
174
|
-
-- Includes
|
175
|
-
--[[
|
176
|
-
Add marker if needed when a job is available.
|
177
|
-
]]
|
178
|
-
local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
|
179
|
-
if not isPausedOrMaxed then
|
180
|
-
rcall("ZADD", markerKey, 0, "0")
|
181
|
-
end
|
182
|
-
end
|
183
|
-
local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
|
184
|
-
rcall(pushCmd, targetKey, jobId)
|
185
|
-
addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
|
186
|
-
end
|
187
|
-
--[[
|
188
|
-
Functions to destructure job key.
|
189
|
-
Just a bit of warning, these functions may be a bit slow and affect performance significantly.
|
190
|
-
]]
|
191
|
-
local getJobIdFromKey = function (jobKey)
|
192
|
-
return string.match(jobKey, ".*:(.*)")
|
193
|
-
end
|
194
|
-
local getJobKeyPrefix = function (jobKey, jobId)
|
195
|
-
return string.sub(jobKey, 0, #jobKey - #jobId)
|
196
|
-
end
|
197
|
-
--[[
|
198
|
-
Function to check for the meta.paused key to decide if we are paused or not
|
199
|
-
(since an empty list and !EXISTS are not really the same).
|
200
|
-
]]
|
201
|
-
local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
|
202
|
-
local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency")
|
203
|
-
if queueAttributes[1] then
|
204
|
-
return pausedKey, true
|
205
|
-
else
|
206
|
-
if queueAttributes[2] then
|
207
|
-
local activeCount = rcall("LLEN", activeKey)
|
208
|
-
if activeCount >= tonumber(queueAttributes[2]) then
|
209
|
-
return waitKey, true
|
210
|
-
else
|
211
|
-
return waitKey, false
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
return waitKey, false
|
216
|
-
end
|
217
|
-
local function moveParentToWait(parentPrefix, parentId, emitEvent)
|
218
|
-
local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
|
219
|
-
parentPrefix .. "wait", parentPrefix .. "paused")
|
220
|
-
addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
|
221
|
-
if emitEvent then
|
222
|
-
local parentEventStream = parentPrefix .. "events"
|
223
|
-
rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
|
224
|
-
end
|
225
|
-
end
|
226
|
-
local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
|
227
|
-
if parentKey then
|
228
|
-
local parentDependenciesKey = parentKey .. ":dependencies"
|
229
|
-
local result = rcall("SREM", parentDependenciesKey, jobKey)
|
230
|
-
if result > 0 then
|
231
|
-
local pendingDependencies = rcall("SCARD", parentDependenciesKey)
|
232
|
-
if pendingDependencies == 0 then
|
233
|
-
local parentId = getJobIdFromKey(parentKey)
|
234
|
-
local parentPrefix = getJobKeyPrefix(parentKey, parentId)
|
235
|
-
local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
|
236
|
-
if numRemovedElements == 1 then
|
237
|
-
if hard then -- remove parent in same queue
|
238
|
-
if parentPrefix == baseKey then
|
239
|
-
removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
|
240
|
-
removeJobKeys(parentKey)
|
241
|
-
if debounceId then
|
242
|
-
rcall("DEL", parentPrefix .. "de:" .. debounceId)
|
243
|
-
end
|
244
|
-
else
|
245
|
-
moveParentToWait(parentPrefix, parentId)
|
246
|
-
end
|
247
|
-
else
|
248
|
-
moveParentToWait(parentPrefix, parentId, true)
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
return true
|
253
|
-
end
|
254
|
-
else
|
255
|
-
local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
|
256
|
-
local missedParentKey = parentAttributes[1]
|
257
|
-
if( (type(missedParentKey) == "string") and missedParentKey ~= ""
|
258
|
-
and (rcall("EXISTS", missedParentKey) == 1)) then
|
259
|
-
local parentDependenciesKey = missedParentKey .. ":dependencies"
|
260
|
-
local result = rcall("SREM", parentDependenciesKey, jobKey)
|
261
|
-
if result > 0 then
|
262
|
-
local pendingDependencies = rcall("SCARD", parentDependenciesKey)
|
263
|
-
if pendingDependencies == 0 then
|
264
|
-
local parentId = getJobIdFromKey(missedParentKey)
|
265
|
-
local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
|
266
|
-
local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
|
267
|
-
if numRemovedElements == 1 then
|
268
|
-
if hard then
|
269
|
-
if parentPrefix == baseKey then
|
270
|
-
removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
|
271
|
-
removeJobKeys(missedParentKey)
|
272
|
-
if parentAttributes[2] then
|
273
|
-
rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
|
274
|
-
end
|
275
|
-
else
|
276
|
-
moveParentToWait(parentPrefix, parentId)
|
277
|
-
end
|
278
|
-
else
|
279
|
-
moveParentToWait(parentPrefix, parentId, true)
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
return true
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|
287
|
-
return false
|
288
|
-
end
|
289
|
-
local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
|
290
|
-
local jobKey = baseKey .. jobId
|
291
|
-
removeParentDependencyKey(jobKey, hard, nil, baseKey)
|
292
|
-
if shouldRemoveDeduplicationKey then
|
293
|
-
removeDeduplicationKey(baseKey, jobKey)
|
294
|
-
end
|
295
|
-
removeJobKeys(jobKey)
|
296
|
-
end
|
297
|
-
local function storeRepeatableJob(schedulerId, schedulerKey, repeatKey, nextMillis, opts, templateData, templateOpts)
|
298
|
-
rcall("ZADD", repeatKey, nextMillis, schedulerId)
|
299
|
-
local optionalValues = {}
|
300
|
-
if opts['tz'] then
|
301
|
-
table.insert(optionalValues, "tz")
|
302
|
-
table.insert(optionalValues, opts['tz'])
|
303
|
-
end
|
304
|
-
if opts['limit'] then
|
305
|
-
table.insert(optionalValues, "limit")
|
306
|
-
table.insert(optionalValues, opts['limit'])
|
307
|
-
end
|
308
|
-
if opts['pattern'] then
|
309
|
-
table.insert(optionalValues, "pattern")
|
310
|
-
table.insert(optionalValues, opts['pattern'])
|
311
|
-
end
|
312
|
-
if opts['endDate'] then
|
313
|
-
table.insert(optionalValues, "endDate")
|
314
|
-
table.insert(optionalValues, opts['endDate'])
|
315
|
-
end
|
316
|
-
if opts['every'] then
|
317
|
-
table.insert(optionalValues, "every")
|
318
|
-
table.insert(optionalValues, opts['every'])
|
319
|
-
end
|
320
|
-
local jsonTemplateOpts = cjson.encode(templateOpts)
|
321
|
-
if jsonTemplateOpts and jsonTemplateOpts ~= '{}' then
|
322
|
-
table.insert(optionalValues, "opts")
|
323
|
-
table.insert(optionalValues, jsonTemplateOpts)
|
324
|
-
end
|
325
|
-
if templateData and templateData ~= '{}' then
|
326
|
-
table.insert(optionalValues, "data")
|
327
|
-
table.insert(optionalValues, templateData)
|
328
|
-
end
|
329
|
-
rcall("HMSET", schedulerKey, "name", opts['name'], "ic", 1,
|
330
|
-
unpack(optionalValues))
|
331
|
-
end
|
332
|
-
local schedulerKey = repeatKey .. ":" .. jobSchedulerId
|
333
|
-
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
334
|
-
local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
|
335
|
-
-- If we are overriding a repeatable job we must delete the delayed job for
|
336
|
-
-- the next iteration.
|
337
|
-
local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
|
338
|
-
if prevMillis ~= false then
|
339
|
-
local delayedJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
|
340
|
-
if rcall("ZSCORE", delayedKey, delayedJobId) ~= false
|
341
|
-
and (rcall("EXISTS", nextDelayedJobKey) ~= 1
|
342
|
-
or delayedJobId == nextDelayedJobId) then
|
343
|
-
removeJob(delayedJobId, true, prefixKey, true --[[remove debounce key]])
|
344
|
-
rcall("ZREM", delayedKey, delayedJobId)
|
345
|
-
end
|
346
|
-
end
|
347
|
-
local schedulerOpts = cmsgpack.unpack(ARGV[2])
|
348
|
-
storeRepeatableJob(jobSchedulerId, schedulerKey, repeatKey, nextMillis, schedulerOpts, ARGV[4], templateOpts)
|
349
|
-
local eventsKey = KEYS[5]
|
350
|
-
local metaKey = KEYS[2]
|
351
|
-
local maxEvents = getOrSetMaxEvents(metaKey)
|
352
|
-
rcall("INCR", KEYS[3])
|
353
|
-
local delayedOpts = cmsgpack.unpack(ARGV[6])
|
354
|
-
addDelayedJob(nextDelayedJobKey, nextDelayedJobId, delayedKey, eventsKey, schedulerOpts['name'], ARGV[4], delayedOpts,
|
355
|
-
timestamp, jobSchedulerId, maxEvents, KEYS[1], nil, nil)
|
356
|
-
if ARGV[9] ~= "" then
|
357
|
-
rcall("HSET", ARGV[9], "nrjid", nextDelayedJobId)
|
358
|
-
end
|
359
|
-
return nextDelayedJobId .. "" -- convert to string
|
360
|
-
`;
|
361
|
-
export const addJobScheduler = {
|
362
|
-
name: 'addJobScheduler',
|
363
|
-
content,
|
364
|
-
keys: 6,
|
365
|
-
};
|
366
|
-
//# sourceMappingURL=addJobScheduler-6.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"addJobScheduler-6.js","sourceRoot":"","sources":["../../../src/scripts/addJobScheduler-6.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuWf,CAAC;AACF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,iBAAiB;IACvB,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}
|
File without changes
|