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.
Files changed (109) hide show
  1. package/dist/cjs/classes/redis-connection.js +1 -1
  2. package/dist/cjs/classes/redis-connection.js.map +1 -1
  3. package/dist/cjs/commands/addJob-8.lua +174 -0
  4. package/dist/cjs/commands/changeDelay-4.lua +43 -0
  5. package/dist/cjs/commands/cleanJobsInSet-2.lua +46 -0
  6. package/dist/cjs/commands/drain-4.lua +25 -0
  7. package/dist/cjs/commands/extendLock-2.lua +23 -0
  8. package/dist/cjs/commands/getState-7.lua +57 -0
  9. package/dist/cjs/commands/getStateV2-7.lua +51 -0
  10. package/dist/cjs/commands/includes/addJobWithPriority.lua +16 -0
  11. package/dist/cjs/commands/includes/batches.lua +18 -0
  12. package/dist/cjs/commands/includes/checkItemInList.lua +12 -0
  13. package/dist/cjs/commands/includes/checkStalledJobs.lua +137 -0
  14. package/dist/cjs/commands/includes/cleanList.lua +50 -0
  15. package/dist/cjs/commands/includes/cleanSet.lua +50 -0
  16. package/dist/cjs/commands/includes/collectMetrics.lua +46 -0
  17. package/dist/cjs/commands/includes/destructureJobKey.lua +12 -0
  18. package/dist/cjs/commands/includes/getNextDelayedTimestamp.lua +13 -0
  19. package/dist/cjs/commands/includes/getTargetQueueList.lua +12 -0
  20. package/dist/cjs/commands/includes/getTimestamp.lua +19 -0
  21. package/dist/cjs/commands/includes/getZSetItems.lua +7 -0
  22. package/dist/cjs/commands/includes/isLocked.lua +31 -0
  23. package/dist/cjs/commands/includes/moveJobFromWaitToActive.lua +84 -0
  24. package/dist/cjs/commands/includes/moveParentFromWaitingChildrenToFailed.lua +28 -0
  25. package/dist/cjs/commands/includes/promoteDelayedJobs.lua +49 -0
  26. package/dist/cjs/commands/includes/removeJob.lua +13 -0
  27. package/dist/cjs/commands/includes/removeJobFromAnyState.lua +26 -0
  28. package/dist/cjs/commands/includes/removeJobs.lua +38 -0
  29. package/dist/cjs/commands/includes/removeJobsByMaxAge.lua +15 -0
  30. package/dist/cjs/commands/includes/removeJobsByMaxCount.lua +15 -0
  31. package/dist/cjs/commands/includes/removeParentDependencyKey.lua +81 -0
  32. package/dist/cjs/commands/includes/trimEvents.lua +12 -0
  33. package/dist/cjs/commands/includes/updateParentDepsIfNeeded.lua +28 -0
  34. package/dist/cjs/commands/isFinished-3.lua +48 -0
  35. package/dist/cjs/commands/isJobInList-1.lua +16 -0
  36. package/dist/cjs/commands/moveStalledJobsToWait-8.lua +24 -0
  37. package/dist/cjs/commands/moveToActive-9.lua +67 -0
  38. package/dist/cjs/commands/moveToDelayed-5.lua +54 -0
  39. package/dist/cjs/commands/moveToFinished-12.lua +201 -0
  40. package/dist/cjs/commands/moveToWaitingChildren-4.lua +62 -0
  41. package/dist/cjs/commands/obliterate-2.lua +94 -0
  42. package/dist/cjs/commands/pause-4.lua +27 -0
  43. package/dist/cjs/commands/promote-6.lua +59 -0
  44. package/dist/cjs/commands/releaseLock-1.lua +19 -0
  45. package/dist/cjs/commands/removeJob-1.lua +72 -0
  46. package/dist/cjs/commands/removeRepeatable-2.lua +32 -0
  47. package/dist/cjs/commands/reprocessJob-4.lua +35 -0
  48. package/dist/cjs/commands/retryJob-6.lua +51 -0
  49. package/dist/cjs/commands/retryJobs-6.lua +53 -0
  50. package/dist/cjs/commands/takeLock-1.lua +17 -0
  51. package/dist/cjs/commands/updateData-1.lua +16 -0
  52. package/dist/cjs/commands/updateProgress-2.lua +22 -0
  53. package/dist/cjs/scripts/moveToFinished-12.js +5 -2
  54. package/dist/cjs/scripts/moveToFinished-12.js.map +1 -1
  55. package/dist/esm/classes/redis-connection.js +1 -1
  56. package/dist/esm/classes/redis-connection.js.map +1 -1
  57. package/dist/esm/commands/addJob-8.lua +174 -0
  58. package/dist/esm/commands/changeDelay-4.lua +43 -0
  59. package/dist/esm/commands/cleanJobsInSet-2.lua +46 -0
  60. package/dist/esm/commands/drain-4.lua +25 -0
  61. package/dist/esm/commands/extendLock-2.lua +23 -0
  62. package/dist/esm/commands/getState-7.lua +57 -0
  63. package/dist/esm/commands/getStateV2-7.lua +51 -0
  64. package/dist/esm/commands/includes/addJobWithPriority.lua +16 -0
  65. package/dist/esm/commands/includes/batches.lua +18 -0
  66. package/dist/esm/commands/includes/checkItemInList.lua +12 -0
  67. package/dist/esm/commands/includes/checkStalledJobs.lua +137 -0
  68. package/dist/esm/commands/includes/cleanList.lua +50 -0
  69. package/dist/esm/commands/includes/cleanSet.lua +50 -0
  70. package/dist/esm/commands/includes/collectMetrics.lua +46 -0
  71. package/dist/esm/commands/includes/destructureJobKey.lua +12 -0
  72. package/dist/esm/commands/includes/getNextDelayedTimestamp.lua +13 -0
  73. package/dist/esm/commands/includes/getTargetQueueList.lua +12 -0
  74. package/dist/esm/commands/includes/getTimestamp.lua +19 -0
  75. package/dist/esm/commands/includes/getZSetItems.lua +7 -0
  76. package/dist/esm/commands/includes/isLocked.lua +31 -0
  77. package/dist/esm/commands/includes/moveJobFromWaitToActive.lua +84 -0
  78. package/dist/esm/commands/includes/moveParentFromWaitingChildrenToFailed.lua +28 -0
  79. package/dist/esm/commands/includes/promoteDelayedJobs.lua +49 -0
  80. package/dist/esm/commands/includes/removeJob.lua +13 -0
  81. package/dist/esm/commands/includes/removeJobFromAnyState.lua +26 -0
  82. package/dist/esm/commands/includes/removeJobs.lua +38 -0
  83. package/dist/esm/commands/includes/removeJobsByMaxAge.lua +15 -0
  84. package/dist/esm/commands/includes/removeJobsByMaxCount.lua +15 -0
  85. package/dist/esm/commands/includes/removeParentDependencyKey.lua +81 -0
  86. package/dist/esm/commands/includes/trimEvents.lua +12 -0
  87. package/dist/esm/commands/includes/updateParentDepsIfNeeded.lua +28 -0
  88. package/dist/esm/commands/isFinished-3.lua +48 -0
  89. package/dist/esm/commands/isJobInList-1.lua +16 -0
  90. package/dist/esm/commands/moveStalledJobsToWait-8.lua +24 -0
  91. package/dist/esm/commands/moveToActive-9.lua +67 -0
  92. package/dist/esm/commands/moveToDelayed-5.lua +54 -0
  93. package/dist/esm/commands/moveToFinished-12.lua +201 -0
  94. package/dist/esm/commands/moveToWaitingChildren-4.lua +62 -0
  95. package/dist/esm/commands/obliterate-2.lua +94 -0
  96. package/dist/esm/commands/pause-4.lua +27 -0
  97. package/dist/esm/commands/promote-6.lua +59 -0
  98. package/dist/esm/commands/releaseLock-1.lua +19 -0
  99. package/dist/esm/commands/removeJob-1.lua +72 -0
  100. package/dist/esm/commands/removeRepeatable-2.lua +32 -0
  101. package/dist/esm/commands/reprocessJob-4.lua +35 -0
  102. package/dist/esm/commands/retryJob-6.lua +51 -0
  103. package/dist/esm/commands/retryJobs-6.lua +53 -0
  104. package/dist/esm/commands/takeLock-1.lua +17 -0
  105. package/dist/esm/commands/updateData-1.lua +16 -0
  106. package/dist/esm/commands/updateProgress-2.lua +22 -0
  107. package/dist/esm/scripts/moveToFinished-12.js +5 -2
  108. package/dist/esm/scripts/moveToFinished-12.js.map +1 -1
  109. 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,7 @@
1
+ --[[
2
+ Function to get ZSet items.
3
+ ]]
4
+
5
+ local function getZSetItems(keyName, max)
6
+ return rcall('ZRANGE', keyName, 0, max - 1)
7
+ 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