bullmq 5.34.6 → 5.34.8
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 +34 -38
- package/dist/cjs/classes/job-scheduler.js.map +1 -1
- package/dist/cjs/classes/job.js.map +1 -1
- package/dist/cjs/classes/scripts.js +35 -5
- package/dist/cjs/classes/scripts.js.map +1 -1
- package/dist/cjs/commands/addDelayedJob-6.lua +4 -18
- package/dist/cjs/commands/{addJobScheduler-2.lua → addJobScheduler-6.lua} +44 -15
- package/dist/cjs/commands/includes/addDelayedJob.lua +28 -0
- package/dist/cjs/commands/updateJobScheduler-6.lua +61 -0
- package/dist/cjs/scripts/addDelayedJob-6.js +74 -64
- package/dist/cjs/scripts/addDelayedJob-6.js.map +1 -1
- package/dist/cjs/scripts/{addJobScheduler-2.js → addJobScheduler-6.js} +144 -16
- package/dist/cjs/scripts/addJobScheduler-6.js.map +1 -0
- package/dist/cjs/scripts/index.js +2 -1
- package/dist/cjs/scripts/index.js.map +1 -1
- package/dist/cjs/scripts/updateJobScheduler-6.js +164 -0
- package/dist/cjs/scripts/updateJobScheduler-6.js.map +1 -0
- 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 +34 -38
- package/dist/esm/classes/job-scheduler.js.map +1 -1
- package/dist/esm/classes/job.js.map +1 -1
- package/dist/esm/classes/scripts.d.ts +3 -3
- package/dist/esm/classes/scripts.js +35 -5
- package/dist/esm/classes/scripts.js.map +1 -1
- package/dist/esm/commands/addDelayedJob-6.lua +4 -18
- package/dist/esm/commands/{addJobScheduler-2.lua → addJobScheduler-6.lua} +44 -15
- package/dist/esm/commands/includes/addDelayedJob.lua +28 -0
- package/dist/esm/commands/updateJobScheduler-6.lua +61 -0
- package/dist/esm/scripts/addDelayedJob-6.js +74 -64
- package/dist/esm/scripts/addDelayedJob-6.js.map +1 -1
- package/dist/esm/scripts/{addJobScheduler-2.js → addJobScheduler-6.js} +144 -16
- package/dist/esm/scripts/addJobScheduler-6.js.map +1 -0
- package/dist/esm/scripts/index.d.ts +2 -1
- package/dist/esm/scripts/index.js +2 -1
- package/dist/esm/scripts/index.js.map +1 -1
- package/dist/esm/scripts/updateJobScheduler-6.d.ts +5 -0
- package/dist/esm/scripts/updateJobScheduler-6.js +161 -0
- package/dist/esm/scripts/updateJobScheduler-6.js.map +1 -0
- 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/scripts/addJobScheduler-2.js.map +0 -1
- package/dist/esm/scripts/addJobScheduler-2.js.map +0 -1
- /package/dist/esm/scripts/{addJobScheduler-2.d.ts → addJobScheduler-6.d.ts} +0 -0
@@ -2,8 +2,12 @@
|
|
2
2
|
Adds a job scheduler, i.e. a job factory that creates jobs based on a given schedule (repeat options).
|
3
3
|
|
4
4
|
Input:
|
5
|
-
KEYS[1] '
|
6
|
-
KEYS[2] '
|
5
|
+
KEYS[1] 'marker',
|
6
|
+
KEYS[2] 'meta'
|
7
|
+
KEYS[3] 'id'
|
8
|
+
KEYS[4] 'delayed'
|
9
|
+
KEYS[5] events stream key
|
10
|
+
KEYS[6] 'repeat' key
|
7
11
|
|
8
12
|
ARGV[1] next milliseconds
|
9
13
|
ARGV[2] msgpacked options
|
@@ -14,27 +18,31 @@
|
|
14
18
|
[5] every?
|
15
19
|
ARGV[3] jobs scheduler id
|
16
20
|
ARGV[4] Json stringified template data
|
17
|
-
ARGV[5]
|
18
|
-
ARGV[6]
|
21
|
+
ARGV[5] msgpacked template opts
|
22
|
+
ARGV[6] msgpacked delayed opts
|
23
|
+
ARGV[7] timestamp
|
24
|
+
ARGV[8] prefix key
|
25
|
+
ARGV[9] producer key
|
19
26
|
|
20
27
|
Output:
|
21
|
-
|
28
|
+
next delayed job id - OK
|
22
29
|
]]
|
23
30
|
local rcall = redis.call
|
24
|
-
local repeatKey = KEYS[
|
25
|
-
local delayedKey = KEYS[
|
26
|
-
|
31
|
+
local repeatKey = KEYS[6]
|
32
|
+
local delayedKey = KEYS[4]
|
33
|
+
local timestamp = ARGV[7]
|
27
34
|
local nextMillis = ARGV[1]
|
28
35
|
local jobSchedulerId = ARGV[3]
|
29
36
|
local templateOpts = cmsgpack.unpack(ARGV[5])
|
30
|
-
local prefixKey = ARGV[
|
37
|
+
local prefixKey = ARGV[8]
|
31
38
|
|
32
39
|
-- Includes
|
40
|
+
--- @include "includes/addDelayedJob"
|
41
|
+
--- @include "includes/getOrSetMaxEvents"
|
33
42
|
--- @include "includes/removeJob"
|
34
43
|
|
35
|
-
local function storeRepeatableJob(schedulerId, repeatKey, nextMillis,
|
44
|
+
local function storeRepeatableJob(schedulerId, schedulerKey, repeatKey, nextMillis, opts, templateData, templateOpts)
|
36
45
|
rcall("ZADD", repeatKey, nextMillis, schedulerId)
|
37
|
-
local opts = cmsgpack.unpack(rawOpts)
|
38
46
|
|
39
47
|
local optionalValues = {}
|
40
48
|
if opts['tz'] then
|
@@ -68,17 +76,19 @@ local function storeRepeatableJob(schedulerId, repeatKey, nextMillis, rawOpts, t
|
|
68
76
|
table.insert(optionalValues, templateData)
|
69
77
|
end
|
70
78
|
|
71
|
-
rcall("HMSET",
|
79
|
+
rcall("HMSET", schedulerKey, "name", opts['name'],
|
72
80
|
unpack(optionalValues))
|
73
81
|
end
|
74
82
|
|
83
|
+
local schedulerKey = repeatKey .. ":" .. jobSchedulerId
|
84
|
+
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
85
|
+
local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
|
86
|
+
|
75
87
|
-- If we are overriding a repeatable job we must delete the delayed job for
|
76
88
|
-- the next iteration.
|
77
89
|
local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
|
78
90
|
if prevMillis ~= false then
|
79
91
|
local delayedJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
|
80
|
-
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
81
|
-
local nextDelayedJobKey = repeatKey .. ":" .. jobSchedulerId .. ":" .. nextMillis
|
82
92
|
|
83
93
|
if rcall("ZSCORE", delayedKey, delayedJobId) ~= false
|
84
94
|
and (rcall("EXISTS", nextDelayedJobKey) ~= 1
|
@@ -88,4 +98,23 @@ if prevMillis ~= false then
|
|
88
98
|
end
|
89
99
|
end
|
90
100
|
|
91
|
-
|
101
|
+
local schedulerOpts = cmsgpack.unpack(ARGV[2])
|
102
|
+
|
103
|
+
storeRepeatableJob(jobSchedulerId, schedulerKey, repeatKey, nextMillis, schedulerOpts, ARGV[4], templateOpts)
|
104
|
+
|
105
|
+
local eventsKey = KEYS[5]
|
106
|
+
local metaKey = KEYS[2]
|
107
|
+
local maxEvents = getOrSetMaxEvents(metaKey)
|
108
|
+
|
109
|
+
rcall("INCR", KEYS[3])
|
110
|
+
|
111
|
+
local delayedOpts = cmsgpack.unpack(ARGV[6])
|
112
|
+
|
113
|
+
addDelayedJob(nextDelayedJobKey, nextDelayedJobId, delayedKey, eventsKey, schedulerOpts['name'], ARGV[4], delayedOpts,
|
114
|
+
timestamp, jobSchedulerId, maxEvents, KEYS[1], nil, nil)
|
115
|
+
|
116
|
+
if ARGV[9] ~= "" then
|
117
|
+
rcall("HSET", ARGV[9], "nrjid", nextDelayedJobId)
|
118
|
+
end
|
119
|
+
|
120
|
+
return nextDelayedJobId .. "" -- convert to string
|
@@ -0,0 +1,28 @@
|
|
1
|
+
--[[
|
2
|
+
Adds a delayed job to the queue by doing the following:
|
3
|
+
- Creates a new job key with the job data.
|
4
|
+
- adds to delayed zset.
|
5
|
+
- Emits a global event 'delayed' if the job is delayed.
|
6
|
+
]]
|
7
|
+
|
8
|
+
-- Includes
|
9
|
+
--- @include "addDelayMarkerIfNeeded"
|
10
|
+
--- @include "getDelayedScore"
|
11
|
+
--- @include "storeJob"
|
12
|
+
|
13
|
+
local function addDelayedJob(jobIdKey, jobId, delayedKey, eventsKey, name, data, opts, timestamp, repeatJobKey,
|
14
|
+
maxEvents, markerKey, parentKey, parentData)
|
15
|
+
-- Store the job.
|
16
|
+
local delay, priority = storeJob(eventsKey, jobIdKey, jobId, name, data,
|
17
|
+
opts, timestamp, parentKey, parentData, repeatJobKey)
|
18
|
+
|
19
|
+
local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
|
20
|
+
|
21
|
+
rcall("ZADD", delayedKey, score, jobId)
|
22
|
+
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
|
23
|
+
"jobId", jobId, "delay", delayedTimestamp)
|
24
|
+
|
25
|
+
-- mark that a delayed job is available
|
26
|
+
addDelayMarkerIfNeeded(markerKey, delayedKey)
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
--[[
|
2
|
+
Updates a job scheduler and adds next delayed job
|
3
|
+
|
4
|
+
Input:
|
5
|
+
KEYS[1] 'marker',
|
6
|
+
KEYS[2] 'meta'
|
7
|
+
KEYS[3] 'id'
|
8
|
+
KEYS[4] 'delayed'
|
9
|
+
KEYS[5] events stream key
|
10
|
+
KEYS[6] 'repeat' key
|
11
|
+
|
12
|
+
ARGV[1] next milliseconds
|
13
|
+
ARGV[2] jobs scheduler id
|
14
|
+
ARGV[3] msgpacked delayed opts
|
15
|
+
ARGV[4] timestamp
|
16
|
+
ARGV[5] prefix key
|
17
|
+
ARGV[6] producer key
|
18
|
+
|
19
|
+
Output:
|
20
|
+
next delayed job id - OK
|
21
|
+
]]
|
22
|
+
local rcall = redis.call
|
23
|
+
local repeatKey = KEYS[6]
|
24
|
+
local delayedKey = KEYS[4]
|
25
|
+
local timestamp = ARGV[4]
|
26
|
+
local nextMillis = ARGV[1]
|
27
|
+
local jobSchedulerId = ARGV[2]
|
28
|
+
local prefixKey = ARGV[5]
|
29
|
+
|
30
|
+
-- Includes
|
31
|
+
--- @include "includes/addDelayedJob"
|
32
|
+
--- @include "includes/getOrSetMaxEvents"
|
33
|
+
|
34
|
+
local schedulerKey = repeatKey .. ":" .. jobSchedulerId
|
35
|
+
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
36
|
+
local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
|
37
|
+
|
38
|
+
-- Validate that scheduler exists.
|
39
|
+
local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
|
40
|
+
if prevMillis ~= false then
|
41
|
+
local schedulerAttributes = rcall("HMGET", schedulerKey, "name", "data")
|
42
|
+
|
43
|
+
rcall("ZADD", repeatKey, nextMillis, jobSchedulerId)
|
44
|
+
|
45
|
+
local eventsKey = KEYS[5]
|
46
|
+
local metaKey = KEYS[2]
|
47
|
+
local maxEvents = getOrSetMaxEvents(metaKey)
|
48
|
+
|
49
|
+
rcall("INCR", KEYS[3])
|
50
|
+
|
51
|
+
local delayedOpts = cmsgpack.unpack(ARGV[3])
|
52
|
+
|
53
|
+
addDelayedJob(nextDelayedJobKey, nextDelayedJobId, delayedKey, eventsKey, schedulerAttributes[1],
|
54
|
+
schedulerAttributes[2] or "{}", delayedOpts, timestamp, jobSchedulerId, maxEvents, KEYS[1], nil, nil)
|
55
|
+
|
56
|
+
if ARGV[6] ~= "" then
|
57
|
+
rcall("HSET", ARGV[6], "nrjid", nextDelayedJobId)
|
58
|
+
end
|
59
|
+
|
60
|
+
return nextDelayedJobId .. "" -- convert to string
|
61
|
+
end
|
@@ -45,6 +45,13 @@ local repeatJobKey = args[9]
|
|
45
45
|
local deduplicationKey = args[10]
|
46
46
|
local parentData
|
47
47
|
-- Includes
|
48
|
+
--[[
|
49
|
+
Adds a delayed job to the queue by doing the following:
|
50
|
+
- Creates a new job key with the job data.
|
51
|
+
- adds to delayed zset.
|
52
|
+
- Emits a global event 'delayed' if the job is delayed.
|
53
|
+
]]
|
54
|
+
-- Includes
|
48
55
|
--[[
|
49
56
|
Add delay marker if needed.
|
50
57
|
]]
|
@@ -69,29 +76,6 @@ local function addDelayMarkerIfNeeded(markerKey, delayedKey)
|
|
69
76
|
rcall("ZADD", markerKey, nextTimestamp, "1")
|
70
77
|
end
|
71
78
|
end
|
72
|
-
--[[
|
73
|
-
Function to debounce a job.
|
74
|
-
]]
|
75
|
-
local function deduplicateJob(prefixKey, deduplicationOpts, jobId, deduplicationKey, eventsKey, maxEvents)
|
76
|
-
local deduplicationId = deduplicationOpts and deduplicationOpts['id']
|
77
|
-
if deduplicationId then
|
78
|
-
local ttl = deduplicationOpts['ttl']
|
79
|
-
local deduplicationKeyExists
|
80
|
-
if ttl then
|
81
|
-
deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'PX', ttl, 'NX')
|
82
|
-
else
|
83
|
-
deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
|
84
|
-
end
|
85
|
-
if deduplicationKeyExists then
|
86
|
-
local currentDebounceJobId = rcall('GET', deduplicationKey)
|
87
|
-
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
|
88
|
-
"debounced", "jobId", currentDebounceJobId, "debounceId", deduplicationId)
|
89
|
-
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
|
90
|
-
"deduplicated", "jobId", currentDebounceJobId, "deduplicationId", deduplicationId)
|
91
|
-
return currentDebounceJobId
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
79
|
--[[
|
96
80
|
Bake in the job id first 12 bits into the timestamp
|
97
81
|
to guarantee correct execution order of delayed jobs
|
@@ -116,6 +100,71 @@ local function getDelayedScore(delayedKey, timestamp, delay)
|
|
116
100
|
end
|
117
101
|
return minScore, delayedTimestamp
|
118
102
|
end
|
103
|
+
--[[
|
104
|
+
Function to store a job
|
105
|
+
]]
|
106
|
+
local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
|
107
|
+
parentKey, parentData, repeatJobKey)
|
108
|
+
local jsonOpts = cjson.encode(opts)
|
109
|
+
local delay = opts['delay'] or 0
|
110
|
+
local priority = opts['priority'] or 0
|
111
|
+
local debounceId = opts['de'] and opts['de']['id']
|
112
|
+
local optionalValues = {}
|
113
|
+
if parentKey ~= nil then
|
114
|
+
table.insert(optionalValues, "parentKey")
|
115
|
+
table.insert(optionalValues, parentKey)
|
116
|
+
table.insert(optionalValues, "parent")
|
117
|
+
table.insert(optionalValues, parentData)
|
118
|
+
end
|
119
|
+
if repeatJobKey ~= nil then
|
120
|
+
table.insert(optionalValues, "rjk")
|
121
|
+
table.insert(optionalValues, repeatJobKey)
|
122
|
+
end
|
123
|
+
if debounceId then
|
124
|
+
table.insert(optionalValues, "deid")
|
125
|
+
table.insert(optionalValues, debounceId)
|
126
|
+
end
|
127
|
+
rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
|
128
|
+
"timestamp", timestamp, "delay", delay, "priority", priority,
|
129
|
+
unpack(optionalValues))
|
130
|
+
rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
|
131
|
+
return delay, priority
|
132
|
+
end
|
133
|
+
local function addDelayedJob(jobIdKey, jobId, delayedKey, eventsKey, name, data, opts, timestamp, repeatJobKey,
|
134
|
+
maxEvents, markerKey, parentKey, parentData)
|
135
|
+
-- Store the job.
|
136
|
+
local delay, priority = storeJob(eventsKey, jobIdKey, jobId, name, data,
|
137
|
+
opts, timestamp, parentKey, parentData, repeatJobKey)
|
138
|
+
local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
|
139
|
+
rcall("ZADD", delayedKey, score, jobId)
|
140
|
+
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
|
141
|
+
"jobId", jobId, "delay", delayedTimestamp)
|
142
|
+
-- mark that a delayed job is available
|
143
|
+
addDelayMarkerIfNeeded(markerKey, delayedKey)
|
144
|
+
end
|
145
|
+
--[[
|
146
|
+
Function to debounce a job.
|
147
|
+
]]
|
148
|
+
local function deduplicateJob(prefixKey, deduplicationOpts, jobId, deduplicationKey, eventsKey, maxEvents)
|
149
|
+
local deduplicationId = deduplicationOpts and deduplicationOpts['id']
|
150
|
+
if deduplicationId then
|
151
|
+
local ttl = deduplicationOpts['ttl']
|
152
|
+
local deduplicationKeyExists
|
153
|
+
if ttl then
|
154
|
+
deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'PX', ttl, 'NX')
|
155
|
+
else
|
156
|
+
deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
|
157
|
+
end
|
158
|
+
if deduplicationKeyExists then
|
159
|
+
local currentDebounceJobId = rcall('GET', deduplicationKey)
|
160
|
+
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
|
161
|
+
"debounced", "jobId", currentDebounceJobId, "debounceId", deduplicationId)
|
162
|
+
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
|
163
|
+
"deduplicated", "jobId", currentDebounceJobId, "deduplicationId", deduplicationId)
|
164
|
+
return currentDebounceJobId
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
119
168
|
--[[
|
120
169
|
Function to get max events value or set by default 10000.
|
121
170
|
]]
|
@@ -289,36 +338,6 @@ local function handleDuplicatedJob(jobKey, jobId, currentParentKey, currentParen
|
|
289
338
|
"duplicated", "jobId", jobId)
|
290
339
|
return jobId .. "" -- convert to string
|
291
340
|
end
|
292
|
-
--[[
|
293
|
-
Function to store a job
|
294
|
-
]]
|
295
|
-
local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
|
296
|
-
parentKey, parentData, repeatJobKey)
|
297
|
-
local jsonOpts = cjson.encode(opts)
|
298
|
-
local delay = opts['delay'] or 0
|
299
|
-
local priority = opts['priority'] or 0
|
300
|
-
local debounceId = opts['de'] and opts['de']['id']
|
301
|
-
local optionalValues = {}
|
302
|
-
if parentKey ~= nil then
|
303
|
-
table.insert(optionalValues, "parentKey")
|
304
|
-
table.insert(optionalValues, parentKey)
|
305
|
-
table.insert(optionalValues, "parent")
|
306
|
-
table.insert(optionalValues, parentData)
|
307
|
-
end
|
308
|
-
if repeatJobKey ~= nil then
|
309
|
-
table.insert(optionalValues, "rjk")
|
310
|
-
table.insert(optionalValues, repeatJobKey)
|
311
|
-
end
|
312
|
-
if debounceId then
|
313
|
-
table.insert(optionalValues, "deid")
|
314
|
-
table.insert(optionalValues, debounceId)
|
315
|
-
end
|
316
|
-
rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
|
317
|
-
"timestamp", timestamp, "delay", delay, "priority", priority,
|
318
|
-
unpack(optionalValues))
|
319
|
-
rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
|
320
|
-
return delay, priority
|
321
|
-
end
|
322
341
|
if parentKey ~= nil then
|
323
342
|
if rcall("EXISTS", parentKey) ~= 1 then return -5 end
|
324
343
|
parentData = cjson.encode(parent)
|
@@ -345,17 +364,8 @@ local deduplicationJobId = deduplicateJob(args[1], opts['de'],
|
|
345
364
|
if deduplicationJobId then
|
346
365
|
return deduplicationJobId
|
347
366
|
end
|
348
|
-
|
349
|
-
|
350
|
-
opts, timestamp, parentKey, parentData,
|
351
|
-
repeatJobKey)
|
352
|
-
local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
|
353
|
-
rcall("ZADD", delayedKey, score, jobId)
|
354
|
-
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
|
355
|
-
"jobId", jobId, "delay", delayedTimestamp)
|
356
|
-
-- mark that a delayed job is available
|
357
|
-
local markerKey = KEYS[1]
|
358
|
-
addDelayMarkerIfNeeded(markerKey, delayedKey)
|
367
|
+
addDelayedJob(jobIdKey, jobId, delayedKey, eventsKey, args[3], ARGV[2], opts, timestamp, repeatJobKey,
|
368
|
+
maxEvents, KEYS[1], parentKey, parentData)
|
359
369
|
-- Check if this job is a child of another job, if so add it to the parents dependencies
|
360
370
|
if parentDependenciesKey ~= nil then
|
361
371
|
rcall("SADD", parentDependenciesKey, jobIdKey)
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"addDelayedJob-6.js","sourceRoot":"","sources":["../../../src/scripts/addDelayedJob-6.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG
|
1
|
+
{"version":3,"file":"addDelayedJob-6.js","sourceRoot":"","sources":["../../../src/scripts/addDelayedJob-6.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqXf,CAAC;AACF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,eAAe;IACrB,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}
|
@@ -1,8 +1,12 @@
|
|
1
1
|
const content = `--[[
|
2
2
|
Adds a job scheduler, i.e. a job factory that creates jobs based on a given schedule (repeat options).
|
3
3
|
Input:
|
4
|
-
KEYS[1] '
|
5
|
-
KEYS[2] '
|
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
|
6
10
|
ARGV[1] next milliseconds
|
7
11
|
ARGV[2] msgpacked options
|
8
12
|
[1] name
|
@@ -12,19 +16,131 @@ const content = `--[[
|
|
12
16
|
[5] every?
|
13
17
|
ARGV[3] jobs scheduler id
|
14
18
|
ARGV[4] Json stringified template data
|
15
|
-
ARGV[5]
|
16
|
-
ARGV[6]
|
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
|
17
24
|
Output:
|
18
|
-
|
25
|
+
next delayed job id - OK
|
19
26
|
]]
|
20
27
|
local rcall = redis.call
|
21
|
-
local repeatKey = KEYS[
|
22
|
-
local delayedKey = KEYS[
|
28
|
+
local repeatKey = KEYS[6]
|
29
|
+
local delayedKey = KEYS[4]
|
30
|
+
local timestamp = ARGV[7]
|
23
31
|
local nextMillis = ARGV[1]
|
24
32
|
local jobSchedulerId = ARGV[3]
|
25
33
|
local templateOpts = cmsgpack.unpack(ARGV[5])
|
26
|
-
local prefixKey = ARGV[
|
34
|
+
local prefixKey = ARGV[8]
|
27
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
|
28
144
|
--[[
|
29
145
|
Function to remove job.
|
30
146
|
]]
|
@@ -178,9 +294,8 @@ local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
|
|
178
294
|
end
|
179
295
|
removeJobKeys(jobKey)
|
180
296
|
end
|
181
|
-
local function storeRepeatableJob(schedulerId, repeatKey, nextMillis,
|
297
|
+
local function storeRepeatableJob(schedulerId, schedulerKey, repeatKey, nextMillis, opts, templateData, templateOpts)
|
182
298
|
rcall("ZADD", repeatKey, nextMillis, schedulerId)
|
183
|
-
local opts = cmsgpack.unpack(rawOpts)
|
184
299
|
local optionalValues = {}
|
185
300
|
if opts['tz'] then
|
186
301
|
table.insert(optionalValues, "tz")
|
@@ -207,16 +322,17 @@ local function storeRepeatableJob(schedulerId, repeatKey, nextMillis, rawOpts, t
|
|
207
322
|
table.insert(optionalValues, "data")
|
208
323
|
table.insert(optionalValues, templateData)
|
209
324
|
end
|
210
|
-
rcall("HMSET",
|
325
|
+
rcall("HMSET", schedulerKey, "name", opts['name'],
|
211
326
|
unpack(optionalValues))
|
212
327
|
end
|
328
|
+
local schedulerKey = repeatKey .. ":" .. jobSchedulerId
|
329
|
+
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
330
|
+
local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
|
213
331
|
-- If we are overriding a repeatable job we must delete the delayed job for
|
214
332
|
-- the next iteration.
|
215
333
|
local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
|
216
334
|
if prevMillis ~= false then
|
217
335
|
local delayedJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
|
218
|
-
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
219
|
-
local nextDelayedJobKey = repeatKey .. ":" .. jobSchedulerId .. ":" .. nextMillis
|
220
336
|
if rcall("ZSCORE", delayedKey, delayedJobId) ~= false
|
221
337
|
and (rcall("EXISTS", nextDelayedJobKey) ~= 1
|
222
338
|
or delayedJobId == nextDelayedJobId) then
|
@@ -224,11 +340,23 @@ if prevMillis ~= false then
|
|
224
340
|
rcall("ZREM", delayedKey, delayedJobId)
|
225
341
|
end
|
226
342
|
end
|
227
|
-
|
343
|
+
local schedulerOpts = cmsgpack.unpack(ARGV[2])
|
344
|
+
storeRepeatableJob(jobSchedulerId, schedulerKey, repeatKey, nextMillis, schedulerOpts, ARGV[4], templateOpts)
|
345
|
+
local eventsKey = KEYS[5]
|
346
|
+
local metaKey = KEYS[2]
|
347
|
+
local maxEvents = getOrSetMaxEvents(metaKey)
|
348
|
+
rcall("INCR", KEYS[3])
|
349
|
+
local delayedOpts = cmsgpack.unpack(ARGV[6])
|
350
|
+
addDelayedJob(nextDelayedJobKey, nextDelayedJobId, delayedKey, eventsKey, schedulerOpts['name'], ARGV[4], delayedOpts,
|
351
|
+
timestamp, jobSchedulerId, maxEvents, KEYS[1], nil, nil)
|
352
|
+
if ARGV[9] ~= "" then
|
353
|
+
rcall("HSET", ARGV[9], "nrjid", nextDelayedJobId)
|
354
|
+
end
|
355
|
+
return nextDelayedJobId .. "" -- convert to string
|
228
356
|
`;
|
229
357
|
export const addJobScheduler = {
|
230
358
|
name: 'addJobScheduler',
|
231
359
|
content,
|
232
|
-
keys:
|
360
|
+
keys: 6,
|
233
361
|
};
|
234
|
-
//# sourceMappingURL=addJobScheduler-
|
362
|
+
//# sourceMappingURL=addJobScheduler-6.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"addJobScheduler-6.js","sourceRoot":"","sources":["../../../src/scripts/addJobScheduler-6.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmWf,CAAC;AACF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,iBAAiB;IACvB,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
export * from './addDelayedJob-6';
|
2
|
-
export * from './addJobScheduler-
|
2
|
+
export * from './addJobScheduler-6';
|
3
3
|
export * from './addLog-2';
|
4
4
|
export * from './addParentJob-4';
|
5
5
|
export * from './addPrioritizedJob-8';
|
@@ -41,5 +41,6 @@ export * from './reprocessJob-8';
|
|
41
41
|
export * from './retryJob-11';
|
42
42
|
export * from './saveStacktrace-1';
|
43
43
|
export * from './updateData-1';
|
44
|
+
export * from './updateJobScheduler-6';
|
44
45
|
export * from './updateProgress-3';
|
45
46
|
export * from './updateRepeatableJobMillis-1';
|
@@ -1,5 +1,5 @@
|
|
1
1
|
export * from './addDelayedJob-6';
|
2
|
-
export * from './addJobScheduler-
|
2
|
+
export * from './addJobScheduler-6';
|
3
3
|
export * from './addLog-2';
|
4
4
|
export * from './addParentJob-4';
|
5
5
|
export * from './addPrioritizedJob-8';
|
@@ -41,6 +41,7 @@ export * from './reprocessJob-8';
|
|
41
41
|
export * from './retryJob-11';
|
42
42
|
export * from './saveStacktrace-1';
|
43
43
|
export * from './updateData-1';
|
44
|
+
export * from './updateJobScheduler-6';
|
44
45
|
export * from './updateProgress-3';
|
45
46
|
export * from './updateRepeatableJobMillis-1';
|
46
47
|
//# sourceMappingURL=index.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scripts/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC"}
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scripts/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC"}
|