bullmq 3.13.4 → 3.14.1
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.js +1 -1
- package/dist/cjs/classes/worker.js.map +1 -1
- package/dist/cjs/commands/addJob-8.lua +2 -2
- package/dist/cjs/commands/changeDelay-3.lua +2 -3
- package/dist/cjs/commands/getRanges-1.lua +1 -1
- package/dist/cjs/commands/includes/addDelayMarkerIfNeeded.lua +3 -3
- package/dist/cjs/commands/includes/cleanSet.lua +2 -2
- package/dist/cjs/commands/includes/getRateLimitTTL.lua +1 -1
- package/dist/cjs/commands/includes/promoteDelayedJobs.lua +4 -9
- package/dist/cjs/commands/includes/updateParentDepsIfNeeded.lua +0 -1
- package/dist/cjs/commands/isFinished-3.lua +3 -3
- package/dist/cjs/commands/moveToActive-9.lua +51 -46
- package/dist/cjs/commands/moveToDelayed-8.lua +22 -23
- package/dist/cjs/commands/moveToFinished-12.lua +3 -1
- package/dist/cjs/commands/pause-4.lua +8 -8
- package/dist/cjs/commands/promote-6.lua +7 -3
- package/dist/cjs/commands/removeRepeatable-2.lua +3 -0
- package/dist/cjs/commands/reprocessJob-6.lua +1 -1
- package/dist/cjs/commands/retryJob-8.lua +4 -5
- package/dist/cjs/commands/saveStacktrace-1.lua +2 -3
- package/dist/cjs/commands/updateData-1.lua +6 -2
- package/dist/cjs/commands/updateProgress-2.lua +6 -2
- package/dist/cjs/scripts/addJob-8.js +5 -5
- package/dist/cjs/scripts/changeDelay-3.js +2 -2
- package/dist/cjs/scripts/getRanges-1.js +1 -1
- package/dist/cjs/scripts/isFinished-3.js +3 -3
- package/dist/cjs/scripts/moveToActive-9.js +76 -76
- package/dist/cjs/scripts/moveToDelayed-8.js +29 -32
- package/dist/cjs/scripts/moveToDelayed-8.js.map +1 -1
- package/dist/cjs/scripts/moveToFinished-12.js +21 -23
- package/dist/cjs/scripts/moveToFinished-12.js.map +1 -1
- package/dist/cjs/scripts/pause-4.js +8 -8
- package/dist/cjs/scripts/promote-6.js +6 -3
- package/dist/cjs/scripts/promote-6.js.map +1 -1
- package/dist/cjs/scripts/removeRepeatable-2.js +2 -0
- package/dist/cjs/scripts/removeRepeatable-2.js.map +1 -1
- package/dist/cjs/scripts/reprocessJob-6.js +1 -1
- package/dist/cjs/scripts/retryJob-8.js +7 -10
- package/dist/cjs/scripts/retryJob-8.js.map +1 -1
- package/dist/cjs/scripts/saveStacktrace-1.js +1 -1
- package/dist/cjs/scripts/updateData-1.js +4 -1
- package/dist/cjs/scripts/updateData-1.js.map +1 -1
- package/dist/cjs/scripts/updateProgress-2.js +3 -0
- package/dist/cjs/scripts/updateProgress-2.js.map +1 -1
- package/dist/cjs/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/esm/classes/job.js +1 -1
- package/dist/esm/classes/worker.d.ts +2 -2
- package/dist/esm/classes/worker.js.map +1 -1
- package/dist/esm/commands/addJob-8.lua +2 -2
- package/dist/esm/commands/changeDelay-3.lua +2 -3
- package/dist/esm/commands/getRanges-1.lua +1 -1
- package/dist/esm/commands/includes/addDelayMarkerIfNeeded.lua +3 -3
- package/dist/esm/commands/includes/cleanSet.lua +2 -2
- package/dist/esm/commands/includes/getRateLimitTTL.lua +1 -1
- package/dist/esm/commands/includes/promoteDelayedJobs.lua +4 -9
- package/dist/esm/commands/includes/updateParentDepsIfNeeded.lua +0 -1
- package/dist/esm/commands/isFinished-3.lua +3 -3
- package/dist/esm/commands/moveToActive-9.lua +51 -46
- package/dist/esm/commands/moveToDelayed-8.lua +22 -23
- package/dist/esm/commands/moveToFinished-12.lua +3 -1
- package/dist/esm/commands/pause-4.lua +8 -8
- package/dist/esm/commands/promote-6.lua +7 -3
- package/dist/esm/commands/removeRepeatable-2.lua +3 -0
- package/dist/esm/commands/reprocessJob-6.lua +1 -1
- package/dist/esm/commands/retryJob-8.lua +4 -5
- package/dist/esm/commands/saveStacktrace-1.lua +2 -3
- package/dist/esm/commands/updateData-1.lua +6 -2
- package/dist/esm/commands/updateProgress-2.lua +6 -2
- package/dist/esm/scripts/addJob-8.js +5 -5
- package/dist/esm/scripts/changeDelay-3.js +2 -2
- package/dist/esm/scripts/getRanges-1.js +1 -1
- package/dist/esm/scripts/isFinished-3.js +3 -3
- package/dist/esm/scripts/moveToActive-9.js +76 -76
- package/dist/esm/scripts/moveToDelayed-8.js +29 -32
- package/dist/esm/scripts/moveToDelayed-8.js.map +1 -1
- package/dist/esm/scripts/moveToFinished-12.js +21 -23
- package/dist/esm/scripts/moveToFinished-12.js.map +1 -1
- package/dist/esm/scripts/pause-4.js +8 -8
- package/dist/esm/scripts/promote-6.js +6 -3
- package/dist/esm/scripts/promote-6.js.map +1 -1
- package/dist/esm/scripts/removeRepeatable-2.js +2 -0
- package/dist/esm/scripts/removeRepeatable-2.js.map +1 -1
- package/dist/esm/scripts/reprocessJob-6.js +1 -1
- package/dist/esm/scripts/retryJob-8.js +7 -10
- package/dist/esm/scripts/retryJob-8.js.map +1 -1
- package/dist/esm/scripts/saveStacktrace-1.js +1 -1
- package/dist/esm/scripts/updateData-1.js +4 -1
- package/dist/esm/scripts/updateData-1.js.map +1 -1
- package/dist/esm/scripts/updateProgress-2.js +3 -0
- package/dist/esm/scripts/updateProgress-2.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
@@ -7,29 +7,29 @@
|
|
7
7
|
so that no other worker picks this job again.
|
8
8
|
|
9
9
|
Input:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
KEYS[1] wait key
|
11
|
+
KEYS[2] active key
|
12
|
+
KEYS[3] priority key
|
13
|
+
KEYS[4] stream events key
|
14
|
+
KEYS[5] stalled key
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
-- Rate limiting
|
17
|
+
KEYS[6] rate limiter key
|
18
|
+
KEYS[7] delayed key
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
-- Promote delayed jobs
|
21
|
+
KEYS[8] paused key
|
22
|
+
KEYS[9] meta key
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
-- Arguments
|
25
|
+
ARGV[1] key prefix
|
26
|
+
ARGV[2] timestamp
|
27
|
+
ARGV[3] optional job ID
|
28
|
+
ARGV[4] opts
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
opts - token - lock token
|
31
|
+
opts - lockDuration
|
32
|
+
opts - limiter
|
33
33
|
]]
|
34
34
|
local jobId
|
35
35
|
local rcall = redis.call
|
@@ -37,47 +37,52 @@ local rcall = redis.call
|
|
37
37
|
-- Includes
|
38
38
|
--- @include "includes/moveJobFromWaitToActive"
|
39
39
|
--- @include "includes/getNextDelayedTimestamp"
|
40
|
-
--- @include "includes/promoteDelayedJobs"
|
41
40
|
--- @include "includes/getRateLimitTTL"
|
41
|
+
--- @include "includes/getTargetQueueList"
|
42
|
+
--- @include "includes/promoteDelayedJobs"
|
43
|
+
|
44
|
+
local target = getTargetQueueList(KEYS[9], KEYS[1], KEYS[8])
|
42
45
|
|
43
46
|
-- Check if there are delayed jobs that we can move to wait.
|
44
|
-
promoteDelayedJobs(KEYS[7],
|
47
|
+
promoteDelayedJobs(KEYS[7], target, KEYS[3], KEYS[4], ARGV[1], ARGV[2])
|
45
48
|
|
46
49
|
local opts
|
47
50
|
if (ARGV[3] ~= "") then
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
+
jobId = ARGV[3]
|
52
|
+
-- clean stalled key
|
53
|
+
rcall("SREM", KEYS[5], jobId)
|
51
54
|
else
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
-- Check if we are rate limited first.
|
56
|
+
opts = cmsgpack.unpack(ARGV[4])
|
57
|
+
local pttl = getRateLimitTTL(opts, KEYS[6])
|
58
|
+
if pttl > 0 then
|
59
|
+
return { 0, 0, pttl }
|
60
|
+
end
|
58
61
|
|
59
|
-
|
60
|
-
|
62
|
+
-- no job ID, try non-blocking move from wait to active
|
63
|
+
jobId = rcall("RPOPLPUSH", KEYS[1], KEYS[2])
|
61
64
|
end
|
62
65
|
|
63
66
|
-- If jobId is special ID 0:delay, then there is no job to process
|
64
|
-
if jobId then
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
if jobId then
|
68
|
+
if string.sub(jobId, 1, 2) == "0:" then
|
69
|
+
rcall("LREM", KEYS[2], 1, jobId)
|
70
|
+
-- Move again since we just got the marker job.
|
71
|
+
jobId = rcall("RPOPLPUSH", KEYS[1], KEYS[2])
|
69
72
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
73
|
+
-- Since it is possible that between a call to BRPOPLPUSH and moveToActive
|
74
|
+
-- another script puts a new maker in wait, we need to check again.
|
75
|
+
if jobId and string.sub(jobId, 1, 2) == "0:" then
|
76
|
+
rcall("LREM", KEYS[2], 1, jobId)
|
77
|
+
jobId = rcall("RPOPLPUSH", KEYS[1], KEYS[2])
|
74
78
|
end
|
79
|
+
end
|
75
80
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
+
if jobId then
|
82
|
+
opts = opts or cmsgpack.unpack(ARGV[4])
|
83
|
+
-- this script is not really moving, it is preparing the job for processing
|
84
|
+
return moveJobFromWaitToActive(KEYS, ARGV[1], jobId, ARGV[2], opts)
|
85
|
+
end
|
81
86
|
end
|
82
87
|
|
83
88
|
-- Return the timestamp for the next delayed job if any.
|
@@ -35,34 +35,33 @@ local rcall = redis.call
|
|
35
35
|
|
36
36
|
local jobKey = KEYS[5]
|
37
37
|
if rcall("EXISTS", jobKey) == 1 then
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
return -2
|
46
|
-
end
|
38
|
+
local delayedKey = KEYS[4]
|
39
|
+
if ARGV[5] ~= "0" then
|
40
|
+
local lockKey = jobKey .. ':lock'
|
41
|
+
if rcall("GET", lockKey) == ARGV[5] then
|
42
|
+
rcall("DEL", lockKey)
|
43
|
+
else
|
44
|
+
return -2
|
47
45
|
end
|
46
|
+
end
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
local jobId = ARGV[4]
|
49
|
+
local score = tonumber(ARGV[3])
|
50
|
+
local delayedTimestamp = (score / 0x1000)
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
local numRemovedElements = rcall("LREM", KEYS[2], -1, jobId)
|
53
|
+
if numRemovedElements < 1 then
|
54
|
+
return -3
|
55
|
+
end
|
57
56
|
|
58
|
-
|
59
|
-
|
57
|
+
rcall("ZADD", delayedKey, score, jobId)
|
58
|
+
rcall("XADD", KEYS[6], "*", "event", "delayed", "jobId", jobId, "delay", delayedTimestamp)
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
-- Check if we need to push a marker job to wake up sleeping workers.
|
61
|
+
local target = getTargetQueueList(KEYS[8], KEYS[1], KEYS[7])
|
62
|
+
addDelayMarkerIfNeeded(target, delayedKey)
|
64
63
|
|
65
|
-
|
64
|
+
return 0
|
66
65
|
else
|
67
|
-
|
66
|
+
return -1
|
68
67
|
end
|
@@ -186,8 +186,10 @@ if rcall("EXISTS", jobIdKey) == 1 then -- // Make sure job exists
|
|
186
186
|
-- and not rate limited.
|
187
187
|
if (ARGV[7] == "1") then
|
188
188
|
|
189
|
+
local target = getTargetQueueList(KEYS[11], KEYS[1], KEYS[8])
|
190
|
+
|
189
191
|
-- Check if there are delayed jobs that can be promoted
|
190
|
-
promoteDelayedJobs(KEYS[7],
|
192
|
+
promoteDelayedJobs(KEYS[7], target, KEYS[3],
|
191
193
|
KEYS[4], ARGV[8], timestamp)
|
192
194
|
|
193
195
|
-- Check if we are rate limited first.
|
@@ -1,16 +1,16 @@
|
|
1
1
|
--[[
|
2
2
|
Pauses or resumes a queue globably.
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
Input:
|
5
|
+
KEYS[1] 'wait' or 'paused''
|
6
|
+
KEYS[2] 'paused' or 'wait'
|
7
|
+
KEYS[3] 'meta'
|
8
|
+
KEYS[4] events stream key
|
9
9
|
|
10
|
-
|
10
|
+
ARGV[1] 'paused' or 'resumed'
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
Event:
|
13
|
+
publish paused or resumed event.
|
14
14
|
]]
|
15
15
|
local rcall = redis.call
|
16
16
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
--[[
|
2
2
|
Promotes a job that is currently "delayed" to the "waiting" state
|
3
3
|
|
4
|
-
|
4
|
+
Input:
|
5
5
|
KEYS[1] 'delayed'
|
6
6
|
KEYS[2] 'wait'
|
7
7
|
KEYS[3] 'paused'
|
@@ -12,10 +12,14 @@
|
|
12
12
|
ARGV[1] queue.toKey('')
|
13
13
|
ARGV[2] jobId
|
14
14
|
|
15
|
-
|
15
|
+
Output:
|
16
|
+
0 - OK
|
17
|
+
-3 - Job not in delayed zset.
|
18
|
+
|
19
|
+
Events:
|
16
20
|
'waiting'
|
17
21
|
]]
|
18
|
-
local rcall = redis.call
|
22
|
+
local rcall = redis.call
|
19
23
|
local jobId = ARGV[2]
|
20
24
|
|
21
25
|
-- Includes
|
@@ -31,7 +31,8 @@ local rcall = redis.call
|
|
31
31
|
--- @include "includes/getTargetQueueList"
|
32
32
|
--- @include "includes/promoteDelayedJobs"
|
33
33
|
|
34
|
-
|
34
|
+
local target = getTargetQueueList(KEYS[5], KEYS[2], KEYS[3])
|
35
|
+
promoteDelayedJobs(KEYS[7], target, KEYS[8], KEYS[6], ARGV[1], ARGV[2])
|
35
36
|
|
36
37
|
if rcall("EXISTS", KEYS[4]) == 1 then
|
37
38
|
|
@@ -44,14 +45,12 @@ if rcall("EXISTS", KEYS[4]) == 1 then
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
|
-
local target = getTargetQueueList(KEYS[5], KEYS[2], KEYS[3])
|
48
|
-
|
49
48
|
rcall("LREM", KEYS[1], 0, ARGV[4])
|
50
49
|
rcall(ARGV[3], target, ARGV[4])
|
51
50
|
|
52
51
|
-- Emit waiting event
|
53
|
-
rcall("XADD", KEYS[6], "*", "event", "waiting", "jobId", ARGV[4], "prev", "failed")
|
54
|
-
|
52
|
+
rcall("XADD", KEYS[6], "*", "event", "waiting", "jobId", ARGV[4], "prev", "failed")
|
53
|
+
|
55
54
|
return 0
|
56
55
|
else
|
57
56
|
return -1
|
@@ -8,15 +8,14 @@
|
|
8
8
|
ARGV[2] failedReason
|
9
9
|
|
10
10
|
Output:
|
11
|
-
|
11
|
+
0 - OK
|
12
12
|
-1 - Missing key
|
13
13
|
]]
|
14
14
|
local rcall = redis.call
|
15
15
|
|
16
16
|
if rcall("EXISTS", KEYS[1]) == 1 then
|
17
|
-
|
18
17
|
rcall("HMSET", KEYS[1], "stacktrace", ARGV[1], "failedReason", ARGV[2])
|
19
|
-
|
18
|
+
|
20
19
|
return 0
|
21
20
|
else
|
22
21
|
return -1
|
@@ -65,11 +65,11 @@ local function getNextDelayedTimestamp(delayedKey)
|
|
65
65
|
return nextTimestamp
|
66
66
|
end
|
67
67
|
end
|
68
|
-
local function addDelayMarkerIfNeeded(
|
69
|
-
if rcall("LLEN",
|
68
|
+
local function addDelayMarkerIfNeeded(targetKey, delayedKey)
|
69
|
+
if rcall("LLEN", targetKey) == 0 then
|
70
70
|
local nextTimestamp = getNextDelayedTimestamp(delayedKey)
|
71
71
|
if nextTimestamp ~= nil then
|
72
|
-
rcall("LPUSH",
|
72
|
+
rcall("LPUSH", targetKey, "0:" .. nextTimestamp)
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
@@ -172,7 +172,7 @@ else
|
|
172
172
|
end
|
173
173
|
rcall("XADD", KEYS[8], "*", "event", "duplicated", "jobId", jobId)
|
174
174
|
return jobId .. "" -- convert to string
|
175
|
-
end
|
175
|
+
end
|
176
176
|
end
|
177
177
|
-- Store the job.
|
178
178
|
local jsonOpts = cjson.encode(opts)
|
@@ -213,7 +213,7 @@ else
|
|
213
213
|
-- Standard or priority add
|
214
214
|
if priority == 0 then
|
215
215
|
-- LIFO or FIFO
|
216
|
-
local pushCmd = opts['lifo'] and 'RPUSH' or 'LPUSH'
|
216
|
+
local pushCmd = opts['lifo'] and 'RPUSH' or 'LPUSH'
|
217
217
|
rcall(pushCmd, target, jobId)
|
218
218
|
else
|
219
219
|
-- Priority add
|
@@ -20,12 +20,12 @@ if rcall("EXISTS", KEYS[2]) == 1 then
|
|
20
20
|
local score = tonumber(ARGV[2])
|
21
21
|
local delayedTimestamp = (score / 0x1000)
|
22
22
|
local numRemovedElements = rcall("ZREM", KEYS[1], jobId)
|
23
|
-
if
|
23
|
+
if numRemovedElements < 1 then
|
24
24
|
return -3
|
25
25
|
end
|
26
26
|
rcall("HSET", KEYS[2], "delay", tonumber(ARGV[1]))
|
27
27
|
rcall("ZADD", KEYS[1], score, jobId)
|
28
|
-
rcall("XADD", KEYS[3], "*", "event", "delayed", "jobId", jobId, "delay", delayedTimestamp)
|
28
|
+
rcall("XADD", KEYS[3], "*", "event", "delayed", "jobId", jobId, "delay", delayedTimestamp)
|
29
29
|
return 0
|
30
30
|
else
|
31
31
|
return -1
|
@@ -10,14 +10,14 @@ const content = `--[[
|
|
10
10
|
0 - Not finished.
|
11
11
|
1 - Completed.
|
12
12
|
2 - Failed.
|
13
|
-
-
|
13
|
+
-1 - Missing job.
|
14
14
|
]]
|
15
15
|
local rcall = redis.call
|
16
16
|
if rcall("EXISTS", KEYS[3]) ~= 1 then
|
17
17
|
if ARGV[2] == "1" then
|
18
|
-
return {-
|
18
|
+
return {-1,"Missing key for job " .. KEYS[3] .. ". isFinished"}
|
19
19
|
end
|
20
|
-
return -
|
20
|
+
return -1
|
21
21
|
end
|
22
22
|
if rcall("ZSCORE", KEYS[1], ARGV[1]) ~= false then
|
23
23
|
if ARGV[2] == "1" then
|
@@ -5,25 +5,25 @@ const content = `--[[
|
|
5
5
|
expiration time. The worker is responsible of keeping the lock fresh
|
6
6
|
so that no other worker picks this job again.
|
7
7
|
Input:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
8
|
+
KEYS[1] wait key
|
9
|
+
KEYS[2] active key
|
10
|
+
KEYS[3] priority key
|
11
|
+
KEYS[4] stream events key
|
12
|
+
KEYS[5] stalled key
|
13
|
+
-- Rate limiting
|
14
|
+
KEYS[6] rate limiter key
|
15
|
+
KEYS[7] delayed key
|
16
|
+
-- Promote delayed jobs
|
17
|
+
KEYS[8] paused key
|
18
|
+
KEYS[9] meta key
|
19
|
+
-- Arguments
|
20
|
+
ARGV[1] key prefix
|
21
|
+
ARGV[2] timestamp
|
22
|
+
ARGV[3] optional job ID
|
23
|
+
ARGV[4] opts
|
24
|
+
opts - token - lock token
|
25
|
+
opts - lockDuration
|
26
|
+
opts - limiter
|
27
27
|
]]
|
28
28
|
local jobId
|
29
29
|
local rcall = redis.call
|
@@ -93,13 +93,36 @@ local function getNextDelayedTimestamp(delayedKey)
|
|
93
93
|
return nextTimestamp
|
94
94
|
end
|
95
95
|
end
|
96
|
+
local function getRateLimitTTL(opts, limiterKey)
|
97
|
+
local maxJobs = tonumber(opts['limiter'] and opts['limiter']['max'])
|
98
|
+
if maxJobs then
|
99
|
+
local jobCounter = tonumber(rcall("GET", limiterKey))
|
100
|
+
if jobCounter ~= nil and jobCounter >= maxJobs then
|
101
|
+
local pttl = rcall("PTTL", limiterKey)
|
102
|
+
if pttl > 0 then
|
103
|
+
return pttl
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
return 0
|
108
|
+
end
|
109
|
+
--[[
|
110
|
+
Function to check for the meta.paused key to decide if we are paused or not
|
111
|
+
(since an empty list and !EXISTS are not really the same).
|
112
|
+
]]
|
113
|
+
local function getTargetQueueList(queueMetaKey, waitKey, pausedKey)
|
114
|
+
if rcall("HEXISTS", queueMetaKey, "paused") ~= 1 then
|
115
|
+
return waitKey
|
116
|
+
else
|
117
|
+
return pausedKey
|
118
|
+
end
|
119
|
+
end
|
96
120
|
--[[
|
97
121
|
Updates the delay set, by moving delayed jobs that should
|
98
122
|
be processed now to "wait".
|
99
123
|
Events:
|
100
124
|
'waiting'
|
101
125
|
]]
|
102
|
-
local rcall = redis.call
|
103
126
|
-- Includes
|
104
127
|
--[[
|
105
128
|
Function to add job considering priority.
|
@@ -115,33 +138,20 @@ local function addJobWithPriority(priorityKey, priority, targetKey, jobId)
|
|
115
138
|
rcall("RPUSH", targetKey, jobId)
|
116
139
|
end
|
117
140
|
end
|
118
|
-
--[[
|
119
|
-
Function to check for the meta.paused key to decide if we are paused or not
|
120
|
-
(since an empty list and !EXISTS are not really the same).
|
121
|
-
]]
|
122
|
-
local function getTargetQueueList(queueMetaKey, waitKey, pausedKey)
|
123
|
-
if rcall("HEXISTS", queueMetaKey, "paused") ~= 1 then
|
124
|
-
return waitKey
|
125
|
-
else
|
126
|
-
return pausedKey
|
127
|
-
end
|
128
|
-
end
|
129
141
|
-- Try to get as much as 1000 jobs at once
|
130
|
-
local function promoteDelayedJobs(delayedKey,
|
131
|
-
|
142
|
+
local function promoteDelayedJobs(delayedKey, targetKey, priorityKey,
|
143
|
+
eventStreamKey, prefix, timestamp)
|
132
144
|
local jobs = rcall("ZRANGEBYSCORE", delayedKey, 0, (timestamp + 1) * 0x1000, "LIMIT", 0, 1000)
|
133
145
|
if (#jobs > 0) then
|
134
146
|
rcall("ZREM", delayedKey, unpack(jobs))
|
135
|
-
-- check if we need to use push in paused instead of waiting
|
136
|
-
local target = getTargetQueueList(metaKey, waitKey, pausedKey)
|
137
147
|
for _, jobId in ipairs(jobs) do
|
138
148
|
local priority =
|
139
149
|
tonumber(rcall("HGET", prefix .. jobId, "priority")) or 0
|
140
150
|
if priority == 0 then
|
141
151
|
-- LIFO or FIFO
|
142
|
-
rcall("LPUSH",
|
152
|
+
rcall("LPUSH", targetKey, jobId)
|
143
153
|
else
|
144
|
-
addJobWithPriority(priorityKey, priority,
|
154
|
+
addJobWithPriority(priorityKey, priority, targetKey, jobId)
|
145
155
|
end
|
146
156
|
-- Emit waiting event
|
147
157
|
rcall("XADD", eventStreamKey, "*", "event", "waiting", "jobId",
|
@@ -150,52 +160,42 @@ local function promoteDelayedJobs(delayedKey, waitKey, priorityKey, pausedKey,
|
|
150
160
|
end
|
151
161
|
end
|
152
162
|
end
|
153
|
-
local
|
154
|
-
local maxJobs = tonumber(opts['limiter'] and opts['limiter']['max'])
|
155
|
-
if maxJobs then
|
156
|
-
local jobCounter = tonumber(rcall("GET", limiterKey))
|
157
|
-
if jobCounter ~= nil and jobCounter >= maxJobs then
|
158
|
-
local pttl = rcall("PTTL", limiterKey)
|
159
|
-
if pttl > 0 then
|
160
|
-
return pttl
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
return 0
|
165
|
-
end
|
163
|
+
local target = getTargetQueueList(KEYS[9], KEYS[1], KEYS[8])
|
166
164
|
-- Check if there are delayed jobs that we can move to wait.
|
167
|
-
promoteDelayedJobs(KEYS[7],
|
165
|
+
promoteDelayedJobs(KEYS[7], target, KEYS[3], KEYS[4], ARGV[1], ARGV[2])
|
168
166
|
local opts
|
169
167
|
if (ARGV[3] ~= "") then
|
170
|
-
|
171
|
-
|
172
|
-
|
168
|
+
jobId = ARGV[3]
|
169
|
+
-- clean stalled key
|
170
|
+
rcall("SREM", KEYS[5], jobId)
|
173
171
|
else
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
172
|
+
-- Check if we are rate limited first.
|
173
|
+
opts = cmsgpack.unpack(ARGV[4])
|
174
|
+
local pttl = getRateLimitTTL(opts, KEYS[6])
|
175
|
+
if pttl > 0 then
|
176
|
+
return { 0, 0, pttl }
|
177
|
+
end
|
178
|
+
-- no job ID, try non-blocking move from wait to active
|
179
|
+
jobId = rcall("RPOPLPUSH", KEYS[1], KEYS[2])
|
182
180
|
end
|
183
181
|
-- If jobId is special ID 0:delay, then there is no job to process
|
184
|
-
if jobId then
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
if jobId then
|
195
|
-
opts = opts or cmsgpack.unpack(ARGV[4])
|
196
|
-
-- this script is not really moving, it is preparing the job for processing
|
197
|
-
return moveJobFromWaitToActive(KEYS, ARGV[1], jobId, ARGV[2], opts)
|
182
|
+
if jobId then
|
183
|
+
if string.sub(jobId, 1, 2) == "0:" then
|
184
|
+
rcall("LREM", KEYS[2], 1, jobId)
|
185
|
+
-- Move again since we just got the marker job.
|
186
|
+
jobId = rcall("RPOPLPUSH", KEYS[1], KEYS[2])
|
187
|
+
-- Since it is possible that between a call to BRPOPLPUSH and moveToActive
|
188
|
+
-- another script puts a new maker in wait, we need to check again.
|
189
|
+
if jobId and string.sub(jobId, 1, 2) == "0:" then
|
190
|
+
rcall("LREM", KEYS[2], 1, jobId)
|
191
|
+
jobId = rcall("RPOPLPUSH", KEYS[1], KEYS[2])
|
198
192
|
end
|
193
|
+
end
|
194
|
+
if jobId then
|
195
|
+
opts = opts or cmsgpack.unpack(ARGV[4])
|
196
|
+
-- this script is not really moving, it is preparing the job for processing
|
197
|
+
return moveJobFromWaitToActive(KEYS, ARGV[1], jobId, ARGV[2], opts)
|
198
|
+
end
|
199
199
|
end
|
200
200
|
-- Return the timestamp for the next delayed job if any.
|
201
201
|
local nextTimestamp = getNextDelayedTimestamp(KEYS[7])
|