bullmq 2.3.1 → 2.3.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/redis-connection.js +1 -1
- package/dist/cjs/classes/redis-connection.js.map +1 -1
- package/dist/cjs/commands/addJob-8.lua +174 -0
- package/dist/cjs/commands/changeDelay-4.lua +43 -0
- package/dist/cjs/commands/cleanJobsInSet-2.lua +46 -0
- package/dist/cjs/commands/drain-4.lua +25 -0
- package/dist/cjs/commands/extendLock-2.lua +23 -0
- package/dist/cjs/commands/getState-7.lua +57 -0
- package/dist/cjs/commands/getStateV2-7.lua +51 -0
- package/dist/cjs/commands/includes/addJobWithPriority.lua +16 -0
- package/dist/cjs/commands/includes/batches.lua +18 -0
- package/dist/cjs/commands/includes/checkItemInList.lua +12 -0
- package/dist/cjs/commands/includes/checkStalledJobs.lua +137 -0
- package/dist/cjs/commands/includes/cleanList.lua +50 -0
- package/dist/cjs/commands/includes/cleanSet.lua +50 -0
- package/dist/cjs/commands/includes/collectMetrics.lua +46 -0
- package/dist/cjs/commands/includes/destructureJobKey.lua +12 -0
- package/dist/cjs/commands/includes/getNextDelayedTimestamp.lua +13 -0
- package/dist/cjs/commands/includes/getTargetQueueList.lua +12 -0
- package/dist/cjs/commands/includes/getTimestamp.lua +19 -0
- package/dist/cjs/commands/includes/getZSetItems.lua +7 -0
- package/dist/cjs/commands/includes/isLocked.lua +31 -0
- package/dist/cjs/commands/includes/moveJobFromWaitToActive.lua +84 -0
- package/dist/cjs/commands/includes/moveParentFromWaitingChildrenToFailed.lua +28 -0
- package/dist/cjs/commands/includes/promoteDelayedJobs.lua +49 -0
- package/dist/cjs/commands/includes/removeJob.lua +13 -0
- package/dist/cjs/commands/includes/removeJobFromAnyState.lua +26 -0
- package/dist/cjs/commands/includes/removeJobs.lua +38 -0
- package/dist/cjs/commands/includes/removeJobsByMaxAge.lua +15 -0
- package/dist/cjs/commands/includes/removeJobsByMaxCount.lua +15 -0
- package/dist/cjs/commands/includes/removeParentDependencyKey.lua +81 -0
- package/dist/cjs/commands/includes/trimEvents.lua +12 -0
- package/dist/cjs/commands/includes/updateParentDepsIfNeeded.lua +28 -0
- package/dist/cjs/commands/isFinished-3.lua +48 -0
- package/dist/cjs/commands/isJobInList-1.lua +16 -0
- package/dist/cjs/commands/moveStalledJobsToWait-8.lua +24 -0
- package/dist/cjs/commands/moveToActive-9.lua +67 -0
- package/dist/cjs/commands/moveToDelayed-5.lua +54 -0
- package/dist/cjs/commands/moveToFinished-12.lua +201 -0
- package/dist/cjs/commands/moveToWaitingChildren-4.lua +62 -0
- package/dist/cjs/commands/obliterate-2.lua +94 -0
- package/dist/cjs/commands/pause-4.lua +27 -0
- package/dist/cjs/commands/promote-6.lua +59 -0
- package/dist/cjs/commands/releaseLock-1.lua +19 -0
- package/dist/cjs/commands/removeJob-1.lua +72 -0
- package/dist/cjs/commands/removeRepeatable-2.lua +32 -0
- package/dist/cjs/commands/reprocessJob-4.lua +35 -0
- package/dist/cjs/commands/retryJob-6.lua +51 -0
- package/dist/cjs/commands/retryJobs-6.lua +53 -0
- package/dist/cjs/commands/takeLock-1.lua +17 -0
- package/dist/cjs/commands/updateData-1.lua +16 -0
- package/dist/cjs/commands/updateProgress-2.lua +22 -0
- package/dist/cjs/scripts/moveToFinished-12.js +5 -2
- package/dist/cjs/scripts/moveToFinished-12.js.map +1 -1
- package/dist/esm/classes/redis-connection.js +1 -1
- package/dist/esm/classes/redis-connection.js.map +1 -1
- package/dist/esm/commands/addJob-8.lua +174 -0
- package/dist/esm/commands/changeDelay-4.lua +43 -0
- package/dist/esm/commands/cleanJobsInSet-2.lua +46 -0
- package/dist/esm/commands/drain-4.lua +25 -0
- package/dist/esm/commands/extendLock-2.lua +23 -0
- package/dist/esm/commands/getState-7.lua +57 -0
- package/dist/esm/commands/getStateV2-7.lua +51 -0
- package/dist/esm/commands/includes/addJobWithPriority.lua +16 -0
- package/dist/esm/commands/includes/batches.lua +18 -0
- package/dist/esm/commands/includes/checkItemInList.lua +12 -0
- package/dist/esm/commands/includes/checkStalledJobs.lua +137 -0
- package/dist/esm/commands/includes/cleanList.lua +50 -0
- package/dist/esm/commands/includes/cleanSet.lua +50 -0
- package/dist/esm/commands/includes/collectMetrics.lua +46 -0
- package/dist/esm/commands/includes/destructureJobKey.lua +12 -0
- package/dist/esm/commands/includes/getNextDelayedTimestamp.lua +13 -0
- package/dist/esm/commands/includes/getTargetQueueList.lua +12 -0
- package/dist/esm/commands/includes/getTimestamp.lua +19 -0
- package/dist/esm/commands/includes/getZSetItems.lua +7 -0
- package/dist/esm/commands/includes/isLocked.lua +31 -0
- package/dist/esm/commands/includes/moveJobFromWaitToActive.lua +84 -0
- package/dist/esm/commands/includes/moveParentFromWaitingChildrenToFailed.lua +28 -0
- package/dist/esm/commands/includes/promoteDelayedJobs.lua +49 -0
- package/dist/esm/commands/includes/removeJob.lua +13 -0
- package/dist/esm/commands/includes/removeJobFromAnyState.lua +26 -0
- package/dist/esm/commands/includes/removeJobs.lua +38 -0
- package/dist/esm/commands/includes/removeJobsByMaxAge.lua +15 -0
- package/dist/esm/commands/includes/removeJobsByMaxCount.lua +15 -0
- package/dist/esm/commands/includes/removeParentDependencyKey.lua +81 -0
- package/dist/esm/commands/includes/trimEvents.lua +12 -0
- package/dist/esm/commands/includes/updateParentDepsIfNeeded.lua +28 -0
- package/dist/esm/commands/isFinished-3.lua +48 -0
- package/dist/esm/commands/isJobInList-1.lua +16 -0
- package/dist/esm/commands/moveStalledJobsToWait-8.lua +24 -0
- package/dist/esm/commands/moveToActive-9.lua +67 -0
- package/dist/esm/commands/moveToDelayed-5.lua +54 -0
- package/dist/esm/commands/moveToFinished-12.lua +201 -0
- package/dist/esm/commands/moveToWaitingChildren-4.lua +62 -0
- package/dist/esm/commands/obliterate-2.lua +94 -0
- package/dist/esm/commands/pause-4.lua +27 -0
- package/dist/esm/commands/promote-6.lua +59 -0
- package/dist/esm/commands/releaseLock-1.lua +19 -0
- package/dist/esm/commands/removeJob-1.lua +72 -0
- package/dist/esm/commands/removeRepeatable-2.lua +32 -0
- package/dist/esm/commands/reprocessJob-4.lua +35 -0
- package/dist/esm/commands/retryJob-6.lua +51 -0
- package/dist/esm/commands/retryJobs-6.lua +53 -0
- package/dist/esm/commands/takeLock-1.lua +17 -0
- package/dist/esm/commands/updateData-1.lua +16 -0
- package/dist/esm/commands/updateProgress-2.lua +22 -0
- package/dist/esm/scripts/moveToFinished-12.js +5 -2
- package/dist/esm/scripts/moveToFinished-12.js.map +1 -1
- package/package.json +2 -2
@@ -0,0 +1,50 @@
|
|
1
|
+
--[[
|
2
|
+
Function to clean job list.
|
3
|
+
Returns jobIds and deleted count number.
|
4
|
+
]]
|
5
|
+
|
6
|
+
-- Includes
|
7
|
+
--- @include "getTimestamp"
|
8
|
+
--- @include "removeJob"
|
9
|
+
|
10
|
+
local function cleanList(listKey, jobKeyPrefix, rangeStart, rangeEnd,
|
11
|
+
timestamp, isWaiting)
|
12
|
+
local jobs = rcall("LRANGE", listKey, rangeStart, rangeEnd)
|
13
|
+
local deleted = {}
|
14
|
+
local deletedCount = 0
|
15
|
+
local jobTS
|
16
|
+
local deletionMarker = ''
|
17
|
+
local jobIdsLen = #jobs
|
18
|
+
for i, job in ipairs(jobs) do
|
19
|
+
if limit > 0 and deletedCount >= limit then
|
20
|
+
break
|
21
|
+
end
|
22
|
+
|
23
|
+
local jobKey = jobKeyPrefix .. job
|
24
|
+
if (isWaiting or rcall("EXISTS", jobKey .. ":lock") == 0) then
|
25
|
+
-- Find the right timestamp of the job to compare to maxTimestamp:
|
26
|
+
-- * finishedOn says when the job was completed, but it isn't set unless the job has actually completed
|
27
|
+
-- * processedOn represents when the job was last attempted, but it doesn't get populated until
|
28
|
+
-- the job is first tried
|
29
|
+
-- * timestamp is the original job submission time
|
30
|
+
-- Fetch all three of these (in that order) and use the first one that is set so that we'll leave jobs
|
31
|
+
-- that have been active within the grace period:
|
32
|
+
jobTS = getTimestamp(jobKey, {"finishedOn", "processedOn", "timestamp"})
|
33
|
+
if (not jobTS or jobTS < timestamp) then
|
34
|
+
-- replace the entry with a deletion marker; the actual deletion will
|
35
|
+
-- occur at the end of the script
|
36
|
+
rcall("LSET", listKey, rangeEnd - jobIdsLen + i, deletionMarker)
|
37
|
+
removeJob(job, true, jobKeyPrefix)
|
38
|
+
if isWaiting then
|
39
|
+
rcall("ZREM", jobKeyPrefix .. "priority", job)
|
40
|
+
end
|
41
|
+
deletedCount = deletedCount + 1
|
42
|
+
table.insert(deleted, job)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
rcall("LREM", listKey, 0, deletionMarker)
|
48
|
+
|
49
|
+
return {deleted, deletedCount}
|
50
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
--[[
|
2
|
+
Function to clean job set.
|
3
|
+
Returns jobIds and deleted count number.
|
4
|
+
]]
|
5
|
+
|
6
|
+
-- Includes
|
7
|
+
--- @include "batches"
|
8
|
+
--- @include "getTimestamp"
|
9
|
+
--- @include "removeJob"
|
10
|
+
|
11
|
+
-- We use ZRANGEBYSCORE to make the case where we're deleting a limited number
|
12
|
+
-- of items in a sorted set only run a single iteration. If we simply used
|
13
|
+
-- ZRANGE, we may take a long time traversing through jobs that are within the
|
14
|
+
-- grace period.
|
15
|
+
local function getJobs(setKey, rangeStart, rangeEnd, maxTimestamp, limit)
|
16
|
+
if limit > 0 then
|
17
|
+
return rcall("ZRANGEBYSCORE", setKey, 0, maxTimestamp, "LIMIT", 0, limit)
|
18
|
+
else
|
19
|
+
return rcall("ZRANGE", setKey, rangeStart, rangeEnd)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
local function cleanSet(setKey, jobKeyPrefix, rangeStart, rangeEnd, timestamp, limit, attributes)
|
24
|
+
local jobs = getJobs(setKey, rangeStart, rangeEnd, timestamp, limit)
|
25
|
+
local deleted = {}
|
26
|
+
local deletedCount = 0
|
27
|
+
local jobTS
|
28
|
+
for i, job in ipairs(jobs) do
|
29
|
+
if limit > 0 and deletedCount >= limit then
|
30
|
+
break
|
31
|
+
end
|
32
|
+
|
33
|
+
local jobKey = jobKeyPrefix .. job
|
34
|
+
-- * finishedOn says when the job was completed, but it isn't set unless the job has actually completed
|
35
|
+
jobTS = getTimestamp(jobKey, attributes)
|
36
|
+
if (not jobTS or jobTS < timestamp) then
|
37
|
+
removeJob(job, true, jobKeyPrefix)
|
38
|
+
deletedCount = deletedCount + 1
|
39
|
+
table.insert(deleted, job)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if(#deleted > 0) then
|
44
|
+
for from, to in batches(#deleted, 7000) do
|
45
|
+
rcall("ZREM", setKey, unpack(deleted, from, to))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
return {deleted, deletedCount}
|
50
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
--[[
|
2
|
+
Functions to collect metrics based on a current and previous count of jobs.
|
3
|
+
Granualarity is fixed at 1 minute.
|
4
|
+
]]
|
5
|
+
--- @include "batches"
|
6
|
+
local function collectMetrics(metaKey, dataPointsList, maxDataPoints,
|
7
|
+
timestamp)
|
8
|
+
-- Increment current count
|
9
|
+
local count = rcall("HINCRBY", metaKey, "count", 1) - 1
|
10
|
+
|
11
|
+
-- Compute how many data points we need to add to the list, N.
|
12
|
+
local prevTS = rcall("HGET", metaKey, "prevTS")
|
13
|
+
|
14
|
+
if not prevTS then
|
15
|
+
-- If prevTS is nil, set it to the current timestamp
|
16
|
+
rcall("HSET", metaKey, "prevTS", timestamp, "prevCount", 0)
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
20
|
+
local N = math.floor((timestamp - prevTS) / 60000)
|
21
|
+
|
22
|
+
if N > 0 then
|
23
|
+
local delta = count - rcall("HGET", metaKey, "prevCount")
|
24
|
+
-- If N > 1, add N-1 zeros to the list
|
25
|
+
if N > 1 then
|
26
|
+
local points = {}
|
27
|
+
points[1] = delta
|
28
|
+
for i = 2, N do
|
29
|
+
points[i] = 0
|
30
|
+
end
|
31
|
+
|
32
|
+
for from, to in batches(#points, 7000) do
|
33
|
+
rcall("LPUSH", dataPointsList, unpack(points, from, to))
|
34
|
+
end
|
35
|
+
else
|
36
|
+
-- LPUSH delta to the list
|
37
|
+
rcall("LPUSH", dataPointsList, delta)
|
38
|
+
end
|
39
|
+
|
40
|
+
-- LTRIM to keep list to its max size
|
41
|
+
rcall("LTRIM", dataPointsList, 0, maxDataPoints - 1)
|
42
|
+
|
43
|
+
-- update prev count with current count
|
44
|
+
rcall("HSET", metaKey, "prevCount", count, "prevTS", timestamp)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
--[[
|
2
|
+
Functions to destructure job key.
|
3
|
+
Just a bit of warning, these functions may be a bit slow and affect performance significantly.
|
4
|
+
]]
|
5
|
+
|
6
|
+
local getJobIdFromKey = function (jobKey)
|
7
|
+
return string.match(jobKey, ".*:(.*)")
|
8
|
+
end
|
9
|
+
|
10
|
+
local getJobKeyPrefix = function (jobKey, jobId)
|
11
|
+
return string.sub(jobKey, 0, #jobKey - #jobId)
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
--[[
|
2
|
+
Function to return the next delayed job timestamp.
|
3
|
+
]]
|
4
|
+
local function getNextDelayedTimestamp(delayedKey)
|
5
|
+
local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
|
6
|
+
if #result then
|
7
|
+
local nextTimestamp = tonumber(result[2])
|
8
|
+
if (nextTimestamp ~= nil) then
|
9
|
+
nextTimestamp = nextTimestamp / 0x1000
|
10
|
+
end
|
11
|
+
return nextTimestamp
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
--[[
|
2
|
+
Function to check for the meta.paused key to decide if we are paused or not
|
3
|
+
(since an empty list and !EXISTS are not really the same).
|
4
|
+
]]
|
5
|
+
|
6
|
+
local function getTargetQueueList(queueMetaKey, waitKey, pausedKey)
|
7
|
+
if rcall("HEXISTS", queueMetaKey, "paused") ~= 1 then
|
8
|
+
return waitKey
|
9
|
+
else
|
10
|
+
return pausedKey
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
--[[
|
2
|
+
Function to get the latest saved timestamp.
|
3
|
+
]]
|
4
|
+
|
5
|
+
local function getTimestamp(jobKey, attributes)
|
6
|
+
if #attributes == 1 then
|
7
|
+
return rcall("HGET", jobKey, attributes[1])
|
8
|
+
end
|
9
|
+
|
10
|
+
local jobTs
|
11
|
+
for _, ts in ipairs(rcall("HMGET", jobKey, unpack(attributes))) do
|
12
|
+
if (ts) then
|
13
|
+
jobTs = ts
|
14
|
+
break
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
return jobTs
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
--[[
|
2
|
+
Function to recursively check if there are no locks
|
3
|
+
on the jobs to be removed.
|
4
|
+
|
5
|
+
returns:
|
6
|
+
boolean
|
7
|
+
]]
|
8
|
+
|
9
|
+
local function isLocked( prefix, jobId)
|
10
|
+
local jobKey = prefix .. jobId;
|
11
|
+
|
12
|
+
-- Check if this job is locked
|
13
|
+
local lockKey = jobKey .. ':lock'
|
14
|
+
local lock = rcall("GET", lockKey)
|
15
|
+
if not lock then
|
16
|
+
local dependencies = rcall("SMEMBERS", jobKey .. ":dependencies")
|
17
|
+
if (#dependencies > 0) then
|
18
|
+
for i, childJobKey in ipairs(dependencies) do
|
19
|
+
-- We need to get the jobId for this job.
|
20
|
+
local childJobId = getJobIdFromKey(childJobKey)
|
21
|
+
local childJobPrefix = getJobKeyPrefix(childJobKey, childJobId)
|
22
|
+
local result = isLocked( childJobPrefix, childJobId )
|
23
|
+
if result then
|
24
|
+
return true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
return false
|
29
|
+
end
|
30
|
+
return true
|
31
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
|
2
|
+
--[[
|
3
|
+
Function to move job from wait state to active.
|
4
|
+
Input:
|
5
|
+
keys[1] wait key
|
6
|
+
keys[2] active key
|
7
|
+
keys[3] priority key
|
8
|
+
keys[4] stream events key
|
9
|
+
keys[5] stalled key
|
10
|
+
|
11
|
+
-- Rate limiting
|
12
|
+
keys[6] rate limiter key
|
13
|
+
keys[7] delayed key
|
14
|
+
|
15
|
+
opts - token - lock token
|
16
|
+
opts - lockDuration
|
17
|
+
opts - limiter
|
18
|
+
]]
|
19
|
+
|
20
|
+
local function moveJobFromWaitToActive(keys, keyPrefix, jobId, processedOn, opts)
|
21
|
+
-- Check if we need to perform rate limiting.
|
22
|
+
local maxJobs = tonumber(opts['limiter'] and opts['limiter']['max'])
|
23
|
+
|
24
|
+
if(maxJobs) then
|
25
|
+
local rateLimiterKey = keys[6];
|
26
|
+
|
27
|
+
local groupKey
|
28
|
+
local groupKeyOpt = opts['limiter'] and opts['limiter']['groupKey'] or ""
|
29
|
+
if groupKeyOpt ~= "" then
|
30
|
+
groupKey = string.match(jobId, "[^:]+$")
|
31
|
+
if groupKey ~= jobId then
|
32
|
+
rateLimiterKey = rateLimiterKey .. ":" .. groupKey
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
local jobCounter
|
37
|
+
|
38
|
+
if groupKey ~= nil then
|
39
|
+
if rateLimiterKey ~= keys[6] then
|
40
|
+
jobCounter = tonumber(rcall("INCR", rateLimiterKey))
|
41
|
+
end
|
42
|
+
else
|
43
|
+
jobCounter = tonumber(rcall("INCR", rateLimiterKey))
|
44
|
+
end
|
45
|
+
|
46
|
+
local limiterDuration = opts['limiter'] and opts['limiter']['duration']
|
47
|
+
-- check if rate limit hit
|
48
|
+
if jobCounter ~= nil and jobCounter > maxJobs then
|
49
|
+
local exceedingJobs = jobCounter - maxJobs
|
50
|
+
local expireTime = tonumber(rcall("PTTL", rateLimiterKey))
|
51
|
+
local delay = expireTime + ((exceedingJobs - 1) * limiterDuration) / maxJobs;
|
52
|
+
local timestamp = delay + tonumber(processedOn)
|
53
|
+
|
54
|
+
-- put job into delayed queue
|
55
|
+
rcall("ZADD", keys[7], timestamp * 0x1000 + bit.band(jobCounter, 0xfff), jobId);
|
56
|
+
rcall("XADD", keys[4], "*", "event", "delayed", "jobId", jobId, "delay", timestamp);
|
57
|
+
|
58
|
+
-- remove from active queue
|
59
|
+
rcall("LREM", keys[2], 1, jobId)
|
60
|
+
|
61
|
+
-- Return when we can process more jobs
|
62
|
+
return expireTime
|
63
|
+
else
|
64
|
+
if jobCounter == 1 then
|
65
|
+
rcall("PEXPIRE", rateLimiterKey, limiterDuration)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
local jobKey = keyPrefix .. jobId
|
71
|
+
local lockKey = jobKey .. ':lock'
|
72
|
+
|
73
|
+
-- get a lock
|
74
|
+
if opts['token'] ~= "0" then
|
75
|
+
rcall("SET", lockKey, opts['token'], "PX", opts['lockDuration'])
|
76
|
+
end
|
77
|
+
|
78
|
+
rcall("ZREM", keys[3], jobId) -- remove from priority
|
79
|
+
rcall("XADD", keys[4], "*", "event", "active", "jobId", jobId, "prev", "waiting")
|
80
|
+
rcall("HSET", jobKey, "processedOn", processedOn)
|
81
|
+
rcall("HINCRBY", jobKey, "attemptsMade", 1)
|
82
|
+
|
83
|
+
return {rcall("HGETALL", jobKey), jobId} -- get job data
|
84
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
--[[
|
2
|
+
Function to recursively move from waitingChildren to failed.
|
3
|
+
]]
|
4
|
+
|
5
|
+
local function moveParentFromWaitingChildrenToFailed( parentQueueKey, parentKey, parentId, jobIdKey, timestamp)
|
6
|
+
if rcall("ZREM", parentQueueKey .. ":waiting-children", parentId) == 1 then
|
7
|
+
rcall("ZADD", parentQueueKey .. ":failed", timestamp, parentId)
|
8
|
+
local failedReason = "child " .. jobIdKey .. " failed"
|
9
|
+
rcall("HMSET", parentKey, "failedReason", failedReason, "finishedOn", timestamp)
|
10
|
+
rcall("XADD", parentQueueKey .. ":events", "*", "event", "failed", "jobId", parentId, "failedReason",
|
11
|
+
failedReason, "prev", "waiting-children")
|
12
|
+
|
13
|
+
local rawParentData = rcall("HGET", parentKey, "parent")
|
14
|
+
|
15
|
+
if rawParentData ~= false then
|
16
|
+
local parentData = cjson.decode(rawParentData)
|
17
|
+
if parentData['fpof'] then
|
18
|
+
moveParentFromWaitingChildrenToFailed(
|
19
|
+
parentData['queueKey'],
|
20
|
+
parentData['queueKey'] .. ':' .. parentData['id'],
|
21
|
+
parentData['id'],
|
22
|
+
parentKey,
|
23
|
+
timestamp
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
--[[
|
2
|
+
Updates the delay set, by moving delayed jobs that should
|
3
|
+
be processed now to "wait".
|
4
|
+
|
5
|
+
Events:
|
6
|
+
'waiting'
|
7
|
+
]]
|
8
|
+
local rcall = redis.call
|
9
|
+
|
10
|
+
-- Includes
|
11
|
+
--- @include "addJobWithPriority"
|
12
|
+
--- @include "getTargetQueueList"
|
13
|
+
|
14
|
+
-- Try to get as much as 1000 jobs at once, and returns the nextTimestamp if
|
15
|
+
-- there are more delayed jobs to process.
|
16
|
+
local function promoteDelayedJobs(delayedKey, waitKey, priorityKey, pausedKey,
|
17
|
+
metaKey, eventStreamKey, prefix, timestamp)
|
18
|
+
local jobs = rcall("ZRANGEBYSCORE", delayedKey, 0, (timestamp + 1) * 0x1000, "LIMIT", 0, 1000)
|
19
|
+
|
20
|
+
if (#jobs > 0) then
|
21
|
+
rcall("ZREM", delayedKey, unpack(jobs))
|
22
|
+
|
23
|
+
-- check if we need to use push in paused instead of waiting
|
24
|
+
local target = getTargetQueueList(metaKey, waitKey, pausedKey)
|
25
|
+
|
26
|
+
for _, jobId in ipairs(jobs) do
|
27
|
+
local priority =
|
28
|
+
tonumber(rcall("HGET", prefix .. jobId, "priority")) or 0
|
29
|
+
|
30
|
+
if priority == 0 then
|
31
|
+
-- LIFO or FIFO
|
32
|
+
rcall("LPUSH", target, jobId)
|
33
|
+
else
|
34
|
+
addJobWithPriority(priorityKey, priority, target, jobId)
|
35
|
+
end
|
36
|
+
|
37
|
+
-- Emit waiting event
|
38
|
+
rcall("XADD", eventStreamKey, "*", "event", "waiting", "jobId",
|
39
|
+
jobId, "prev", "delayed")
|
40
|
+
rcall("HSET", prefix .. jobId, "delay", 0)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
local nextTimestamp = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")[2]
|
45
|
+
if (nextTimestamp ~= nil) then
|
46
|
+
nextTimestamp = nextTimestamp / 0x1000
|
47
|
+
end
|
48
|
+
return nextTimestamp
|
49
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
--[[
|
2
|
+
Function to remove job.
|
3
|
+
]]
|
4
|
+
|
5
|
+
-- Includes
|
6
|
+
--- @include "removeParentDependencyKey"
|
7
|
+
|
8
|
+
local function removeJob(jobId, hard, baseKey)
|
9
|
+
local jobKey = baseKey .. jobId
|
10
|
+
removeParentDependencyKey(jobKey, hard, nil, baseKey)
|
11
|
+
rcall("DEL", jobKey, jobKey .. ':logs',
|
12
|
+
jobKey .. ':dependencies', jobKey .. ':processed')
|
13
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
--[[
|
2
|
+
Function to remove from any state.
|
3
|
+
|
4
|
+
returns:
|
5
|
+
prev state
|
6
|
+
]]
|
7
|
+
|
8
|
+
local function removeJobFromAnyState( prefix, jobId)
|
9
|
+
if rcall("LREM", prefix .. "wait", 0, jobId) == 1 then
|
10
|
+
return "wait"
|
11
|
+
elseif rcall("LREM", prefix .. "paused", 0, jobId) == 1 then
|
12
|
+
return "paused"
|
13
|
+
elseif rcall("LREM", prefix .. "active", 0, jobId) == 1 then
|
14
|
+
return "active"
|
15
|
+
elseif rcall("ZREM", prefix .. "waiting-children", jobId) == 1 then
|
16
|
+
return "waiting-children"
|
17
|
+
elseif rcall("ZREM", prefix .. "delayed", jobId) == 1 then
|
18
|
+
return "delayed"
|
19
|
+
elseif rcall("ZREM", prefix .. "completed", jobId) == 1 then
|
20
|
+
return "completed"
|
21
|
+
elseif rcall("ZREM", prefix .. "failed", jobId) == 1 then
|
22
|
+
return "failed"
|
23
|
+
end
|
24
|
+
|
25
|
+
return "unknown"
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
--[[
|
2
|
+
Functions to remove jobs.
|
3
|
+
]]
|
4
|
+
|
5
|
+
-- Includes
|
6
|
+
--- @include "batches"
|
7
|
+
|
8
|
+
local function getListItems(keyName, max)
|
9
|
+
return rcall('LRANGE', keyName, 0, max - 1)
|
10
|
+
end
|
11
|
+
|
12
|
+
--- @include "getZSetItems"
|
13
|
+
--- @include "removeJob"
|
14
|
+
|
15
|
+
local function removeJobs(keys, hard, baseKey, max)
|
16
|
+
for i, key in ipairs(keys) do
|
17
|
+
removeJob(key, hard, baseKey)
|
18
|
+
end
|
19
|
+
return max - #keys
|
20
|
+
end
|
21
|
+
|
22
|
+
local function removeListJobs(keyName, hard, baseKey, max)
|
23
|
+
local jobs = getListItems(keyName, max)
|
24
|
+
local count = removeJobs(jobs, hard, baseKey, max)
|
25
|
+
rcall("LTRIM", keyName, #jobs, -1)
|
26
|
+
return count
|
27
|
+
end
|
28
|
+
|
29
|
+
local function removeZSetJobs(keyName, hard, baseKey, max)
|
30
|
+
local jobs = getZSetItems(keyName, max)
|
31
|
+
local count = removeJobs(jobs, hard, baseKey, max)
|
32
|
+
if(#jobs > 0) then
|
33
|
+
for from, to in batches(#jobs, 7000) do
|
34
|
+
rcall("ZREM", keyName, unpack(jobs))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
return count
|
38
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
--[[
|
2
|
+
Functions to remove jobs by max age.
|
3
|
+
]]
|
4
|
+
|
5
|
+
-- Includes
|
6
|
+
--- @include "removeJob"
|
7
|
+
|
8
|
+
local function removeJobsByMaxAge(timestamp, maxAge, targetSet, prefix)
|
9
|
+
local start = timestamp - maxAge * 1000
|
10
|
+
local jobIds = rcall("ZREVRANGEBYSCORE", targetSet, start, "-inf")
|
11
|
+
for i, jobId in ipairs(jobIds) do
|
12
|
+
removeJob(jobId, false, prefix)
|
13
|
+
end
|
14
|
+
rcall("ZREMRANGEBYSCORE", targetSet, "-inf", start)
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
--[[
|
2
|
+
Functions to remove jobs by max count.
|
3
|
+
]]
|
4
|
+
|
5
|
+
-- Includes
|
6
|
+
--- @include "removeJob"
|
7
|
+
|
8
|
+
local function removeJobsByMaxCount(maxCount, targetSet, prefix)
|
9
|
+
local start = maxCount
|
10
|
+
local jobIds = rcall("ZREVRANGE", targetSet, start, -1)
|
11
|
+
for i, jobId in ipairs(jobIds) do
|
12
|
+
removeJob(jobId, false, prefix)
|
13
|
+
end
|
14
|
+
rcall("ZREMRANGEBYRANK", targetSet, 0, -(maxCount + 1))
|
15
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
--[[
|
2
|
+
Check if this job has a parent. If so we will just remove it from
|
3
|
+
the parent child list, but if it is the last child we should move the parent to "wait/paused"
|
4
|
+
which requires code from "moveToFinished"
|
5
|
+
]]
|
6
|
+
|
7
|
+
--- @include "destructureJobKey"
|
8
|
+
--- @include "getTargetQueueList"
|
9
|
+
|
10
|
+
local function moveParentToWait(parentPrefix, parentId, emitEvent)
|
11
|
+
local parentTarget = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "wait", parentPrefix .. "paused")
|
12
|
+
rcall("RPUSH", parentTarget, parentId)
|
13
|
+
|
14
|
+
if emitEvent then
|
15
|
+
local parentEventStream = parentPrefix .. "events"
|
16
|
+
rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey)
|
21
|
+
if parentKey then
|
22
|
+
local parentProcessedKey = parentKey .. ":processed"
|
23
|
+
rcall("HDEL", parentProcessedKey, jobKey)
|
24
|
+
local parentDependenciesKey = parentKey .. ":dependencies"
|
25
|
+
local result = rcall("SREM", parentDependenciesKey, jobKey)
|
26
|
+
if result > 0 then
|
27
|
+
local pendingDependencies = rcall("SCARD", parentDependenciesKey)
|
28
|
+
if pendingDependencies == 0 then
|
29
|
+
local parentId = getJobIdFromKey(parentKey)
|
30
|
+
local parentPrefix = getJobKeyPrefix(parentKey, parentId)
|
31
|
+
|
32
|
+
local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
|
33
|
+
|
34
|
+
if numRemovedElements == 1 then
|
35
|
+
if hard then
|
36
|
+
if parentPrefix == baseKey then
|
37
|
+
removeParentDependencyKey(parentKey, hard, nil, baseKey)
|
38
|
+
rcall("DEL", parentKey, parentKey .. ':logs',
|
39
|
+
parentKey .. ':dependencies', parentKey .. ':processed')
|
40
|
+
else
|
41
|
+
moveParentToWait(parentPrefix, parentId)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
moveParentToWait(parentPrefix, parentId, true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
else
|
50
|
+
local missedParentKey = rcall("HGET", jobKey, "parentKey")
|
51
|
+
if( (type(missedParentKey) == "string") and missedParentKey ~= "" and (rcall("EXISTS", missedParentKey) == 1)) then
|
52
|
+
local parentProcessedKey = missedParentKey .. ":processed"
|
53
|
+
rcall("HDEL", parentProcessedKey, jobKey)
|
54
|
+
local parentDependenciesKey = missedParentKey .. ":dependencies"
|
55
|
+
local result = rcall("SREM", parentDependenciesKey, jobKey)
|
56
|
+
if result > 0 then
|
57
|
+
local pendingDependencies = rcall("SCARD", parentDependenciesKey)
|
58
|
+
if pendingDependencies == 0 then
|
59
|
+
local parentId = getJobIdFromKey(missedParentKey)
|
60
|
+
local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
|
61
|
+
|
62
|
+
local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
|
63
|
+
|
64
|
+
if numRemovedElements == 1 then
|
65
|
+
if hard then
|
66
|
+
if parentPrefix == baseKey then
|
67
|
+
removeParentDependencyKey(missedParentKey, hard, nil, baseKey)
|
68
|
+
rcall("DEL", missedParentKey, missedParentKey .. ':logs',
|
69
|
+
missedParentKey .. ':dependencies', missedParentKey .. ':processed')
|
70
|
+
else
|
71
|
+
moveParentToWait(parentPrefix, parentId)
|
72
|
+
end
|
73
|
+
else
|
74
|
+
moveParentToWait(parentPrefix, parentId, true)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
--[[
|
2
|
+
Function to trim events, default 10000.
|
3
|
+
]]
|
4
|
+
|
5
|
+
local function trimEvents(metaKey, eventStreamKey)
|
6
|
+
local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
|
7
|
+
if maxEvents ~= false then
|
8
|
+
rcall("XTRIM", eventStreamKey, "MAXLEN", "~", maxEvents)
|
9
|
+
else
|
10
|
+
rcall("XTRIM", eventStreamKey, "MAXLEN", "~", 10000)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
--[[
|
2
|
+
Validate and move or add dependencies to parent.
|
3
|
+
]]
|
4
|
+
|
5
|
+
-- Includes
|
6
|
+
--- @include "addJobWithPriority"
|
7
|
+
--- @include "getTargetQueueList"
|
8
|
+
|
9
|
+
local function updateParentDepsIfNeeded(parentKey, parentQueueKey, parentDependenciesKey,
|
10
|
+
parentId, jobIdKey, returnvalue )
|
11
|
+
local processedSet = parentKey .. ":processed"
|
12
|
+
rcall("HSET", processedSet, jobIdKey, returnvalue)
|
13
|
+
local activeParent = rcall("ZSCORE", parentQueueKey .. ":waiting-children", parentId)
|
14
|
+
if rcall("SCARD", parentDependenciesKey) == 0 and activeParent then
|
15
|
+
rcall("ZREM", parentQueueKey .. ":waiting-children", parentId)
|
16
|
+
local parentTarget = getTargetQueueList(parentQueueKey .. ":meta", parentQueueKey .. ":wait",
|
17
|
+
parentQueueKey .. ":paused")
|
18
|
+
local priority = tonumber(rcall("HGET", parentKey, "priority"))
|
19
|
+
-- Standard or priority add
|
20
|
+
if priority == 0 then
|
21
|
+
rcall("RPUSH", parentTarget, parentId)
|
22
|
+
else
|
23
|
+
addJobWithPriority(parentQueueKey .. ":priority", priority, parentTarget, parentId)
|
24
|
+
end
|
25
|
+
|
26
|
+
rcall("XADD", parentQueueKey .. ":events", "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
|
27
|
+
end
|
28
|
+
end
|