bullmq 5.47.2 → 5.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/cjs/classes/async-fifo-queue.js.map +1 -1
  2. package/dist/cjs/classes/child.js.map +1 -1
  3. package/dist/cjs/classes/job-scheduler.js +1 -1
  4. package/dist/cjs/classes/job-scheduler.js.map +1 -1
  5. package/dist/cjs/classes/job.js +11 -0
  6. package/dist/cjs/classes/job.js.map +1 -1
  7. package/dist/cjs/classes/queue-base.js.map +1 -1
  8. package/dist/cjs/classes/queue-keys.js.map +1 -1
  9. package/dist/cjs/classes/repeat.js +1 -1
  10. package/dist/cjs/classes/repeat.js.map +1 -1
  11. package/dist/cjs/classes/scripts.js +12 -2
  12. package/dist/cjs/classes/scripts.js.map +1 -1
  13. package/dist/cjs/classes/worker.js.map +1 -1
  14. package/dist/cjs/commands/includes/isLocked.lua +1 -0
  15. package/dist/cjs/commands/includes/removeJobWithChildren.lua +93 -0
  16. package/dist/cjs/commands/removeJob-3.lua +15 -72
  17. package/dist/cjs/commands/removeUnprocessedChildren-2.lua +31 -0
  18. package/dist/cjs/scripts/index.js +1 -0
  19. package/dist/cjs/scripts/index.js.map +1 -1
  20. package/dist/cjs/scripts/removeJob-3.js +83 -55
  21. package/dist/cjs/scripts/removeJob-3.js.map +1 -1
  22. package/dist/cjs/scripts/removeUnprocessedChildren-2.js +332 -0
  23. package/dist/cjs/scripts/removeUnprocessedChildren-2.js.map +1 -0
  24. package/dist/cjs/tsconfig-cjs.tsbuildinfo +1 -1
  25. package/dist/cjs/version.js +1 -1
  26. package/dist/esm/classes/async-fifo-queue.js.map +1 -1
  27. package/dist/esm/classes/child.js.map +1 -1
  28. package/dist/esm/classes/job-scheduler.js +1 -1
  29. package/dist/esm/classes/job-scheduler.js.map +1 -1
  30. package/dist/esm/classes/job.d.ts +9 -1
  31. package/dist/esm/classes/job.js +11 -0
  32. package/dist/esm/classes/job.js.map +1 -1
  33. package/dist/esm/classes/queue-base.js.map +1 -1
  34. package/dist/esm/classes/queue-keys.js.map +1 -1
  35. package/dist/esm/classes/repeat.js +1 -1
  36. package/dist/esm/classes/repeat.js.map +1 -1
  37. package/dist/esm/classes/scripts.d.ts +1 -0
  38. package/dist/esm/classes/scripts.js +12 -2
  39. package/dist/esm/classes/scripts.js.map +1 -1
  40. package/dist/esm/classes/worker.js.map +1 -1
  41. package/dist/esm/commands/includes/isLocked.lua +1 -0
  42. package/dist/esm/commands/includes/removeJobWithChildren.lua +93 -0
  43. package/dist/esm/commands/removeJob-3.lua +15 -72
  44. package/dist/esm/commands/removeUnprocessedChildren-2.lua +31 -0
  45. package/dist/esm/interfaces/queue-options.d.ts +1 -1
  46. package/dist/esm/interfaces/repeat-options.d.ts +1 -1
  47. package/dist/esm/scripts/index.d.ts +1 -0
  48. package/dist/esm/scripts/index.js +1 -0
  49. package/dist/esm/scripts/index.js.map +1 -1
  50. package/dist/esm/scripts/removeJob-3.js +83 -55
  51. package/dist/esm/scripts/removeJob-3.js.map +1 -1
  52. package/dist/esm/scripts/removeUnprocessedChildren-2.d.ts +5 -0
  53. package/dist/esm/scripts/removeUnprocessedChildren-2.js +329 -0
  54. package/dist/esm/scripts/removeUnprocessedChildren-2.js.map +1 -0
  55. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  56. package/dist/esm/version.d.ts +1 -1
  57. package/dist/esm/version.js +1 -1
  58. package/package.json +1 -1
@@ -0,0 +1,332 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removeUnprocessedChildren = void 0;
4
+ const content = `--[[
5
+ Remove a job from all the statuses it may be in as well as all its data.
6
+ In order to be able to remove a job, it cannot be active.
7
+ Input:
8
+ KEYS[1] jobKey
9
+ KEYS[2] meta key
10
+ ARGV[1] prefix
11
+ ARGV[2] jobId
12
+ Events:
13
+ 'removed' for every children removed
14
+ ]]
15
+ -- Includes
16
+ --[[
17
+ Remove a job from all the statuses it may be in as well as all its data,
18
+ including its children. Active children can be ignored.
19
+ Events:
20
+ 'removed'
21
+ ]]
22
+ local rcall = redis.call
23
+ -- Includes
24
+ --[[
25
+ Functions to destructure job key.
26
+ Just a bit of warning, these functions may be a bit slow and affect performance significantly.
27
+ ]]
28
+ local getJobIdFromKey = function (jobKey)
29
+ return string.match(jobKey, ".*:(.*)")
30
+ end
31
+ local getJobKeyPrefix = function (jobKey, jobId)
32
+ return string.sub(jobKey, 0, #jobKey - #jobId)
33
+ end
34
+ --[[
35
+ Function to get max events value or set by default 10000.
36
+ ]]
37
+ local function getOrSetMaxEvents(metaKey)
38
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
39
+ if not maxEvents then
40
+ maxEvents = 10000
41
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
42
+ end
43
+ return maxEvents
44
+ end
45
+ --[[
46
+ Function to check if the job belongs to a job scheduler and
47
+ current delayed job matches with jobId
48
+ ]]
49
+ local function isJobSchedulerJob(jobId, jobKey, jobSchedulersKey)
50
+ local repeatJobKey = rcall("HGET", jobKey, "rjk")
51
+ if repeatJobKey then
52
+ local prevMillis = rcall("ZSCORE", jobSchedulersKey, repeatJobKey)
53
+ if prevMillis then
54
+ local currentDelayedJobId = "repeat:" .. repeatJobKey .. ":" .. prevMillis
55
+ return jobId == currentDelayedJobId
56
+ end
57
+ end
58
+ return false
59
+ end
60
+ --[[
61
+ Function to remove deduplication key.
62
+ ]]
63
+ local function removeDeduplicationKey(prefixKey, jobKey)
64
+ local deduplicationId = rcall("HGET", jobKey, "deid")
65
+ if deduplicationId then
66
+ local deduplicationKey = prefixKey .. "de:" .. deduplicationId
67
+ rcall("DEL", deduplicationKey)
68
+ end
69
+ end
70
+ --[[
71
+ Function to remove from any state.
72
+ returns:
73
+ prev state
74
+ ]]
75
+ local function removeJobFromAnyState( prefix, jobId)
76
+ -- We start with the ZSCORE checks, since they have O(1) complexity
77
+ if rcall("ZSCORE", prefix .. "completed", jobId) then
78
+ rcall("ZREM", prefix .. "completed", jobId)
79
+ return "completed"
80
+ elseif rcall("ZSCORE", prefix .. "waiting-children", jobId) then
81
+ rcall("ZREM", prefix .. "waiting-children", jobId)
82
+ return "waiting-children"
83
+ elseif rcall("ZSCORE", prefix .. "delayed", jobId) then
84
+ rcall("ZREM", prefix .. "delayed", jobId)
85
+ return "delayed"
86
+ elseif rcall("ZSCORE", prefix .. "failed", jobId) then
87
+ rcall("ZREM", prefix .. "failed", jobId)
88
+ return "failed"
89
+ elseif rcall("ZSCORE", prefix .. "prioritized", jobId) then
90
+ rcall("ZREM", prefix .. "prioritized", jobId)
91
+ return "prioritized"
92
+ -- We remove only 1 element from the list, since we assume they are not added multiple times
93
+ elseif rcall("LREM", prefix .. "wait", 1, jobId) == 1 then
94
+ return "wait"
95
+ elseif rcall("LREM", prefix .. "paused", 1, jobId) == 1 then
96
+ return "paused"
97
+ elseif rcall("LREM", prefix .. "active", 1, jobId) == 1 then
98
+ return "active"
99
+ end
100
+ return "unknown"
101
+ end
102
+ --[[
103
+ Function to remove job keys.
104
+ ]]
105
+ local function removeJobKeys(jobKey)
106
+ return rcall("DEL", jobKey, jobKey .. ':logs', jobKey .. ':dependencies',
107
+ jobKey .. ':processed', jobKey .. ':failed', jobKey .. ':unsuccessful')
108
+ end
109
+ --[[
110
+ Check if this job has a parent. If so we will just remove it from
111
+ the parent child list, but if it is the last child we should move the parent to "wait/paused"
112
+ which requires code from "moveToFinished"
113
+ ]]
114
+ -- Includes
115
+ --[[
116
+ Function to add job in target list and add marker if needed.
117
+ ]]
118
+ -- Includes
119
+ --[[
120
+ Add marker if needed when a job is available.
121
+ ]]
122
+ local function addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
123
+ if not isPausedOrMaxed then
124
+ rcall("ZADD", markerKey, 0, "0")
125
+ end
126
+ end
127
+ local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed, jobId)
128
+ rcall(pushCmd, targetKey, jobId)
129
+ addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
130
+ end
131
+ --[[
132
+ Function to check for the meta.paused key to decide if we are paused or not
133
+ (since an empty list and !EXISTS are not really the same).
134
+ ]]
135
+ local function getTargetQueueList(queueMetaKey, activeKey, waitKey, pausedKey)
136
+ local queueAttributes = rcall("HMGET", queueMetaKey, "paused", "concurrency")
137
+ if queueAttributes[1] then
138
+ return pausedKey, true
139
+ else
140
+ if queueAttributes[2] then
141
+ local activeCount = rcall("LLEN", activeKey)
142
+ if activeCount >= tonumber(queueAttributes[2]) then
143
+ return waitKey, true
144
+ else
145
+ return waitKey, false
146
+ end
147
+ end
148
+ end
149
+ return waitKey, false
150
+ end
151
+ local function _moveParentToWait(parentPrefix, parentId, emitEvent)
152
+ local parentTarget, isPausedOrMaxed = getTargetQueueList(parentPrefix .. "meta", parentPrefix .. "active",
153
+ parentPrefix .. "wait", parentPrefix .. "paused")
154
+ addJobInTargetList(parentTarget, parentPrefix .. "marker", "RPUSH", isPausedOrMaxed, parentId)
155
+ if emitEvent then
156
+ local parentEventStream = parentPrefix .. "events"
157
+ rcall("XADD", parentEventStream, "*", "event", "waiting", "jobId", parentId, "prev", "waiting-children")
158
+ end
159
+ end
160
+ local function removeParentDependencyKey(jobKey, hard, parentKey, baseKey, debounceId)
161
+ if parentKey then
162
+ local parentDependenciesKey = parentKey .. ":dependencies"
163
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
164
+ if result > 0 then
165
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
166
+ if pendingDependencies == 0 then
167
+ local parentId = getJobIdFromKey(parentKey)
168
+ local parentPrefix = getJobKeyPrefix(parentKey, parentId)
169
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
170
+ if numRemovedElements == 1 then
171
+ if hard then -- remove parent in same queue
172
+ if parentPrefix == baseKey then
173
+ removeParentDependencyKey(parentKey, hard, nil, baseKey, nil)
174
+ removeJobKeys(parentKey)
175
+ if debounceId then
176
+ rcall("DEL", parentPrefix .. "de:" .. debounceId)
177
+ end
178
+ else
179
+ _moveParentToWait(parentPrefix, parentId)
180
+ end
181
+ else
182
+ _moveParentToWait(parentPrefix, parentId, true)
183
+ end
184
+ end
185
+ end
186
+ return true
187
+ end
188
+ else
189
+ local parentAttributes = rcall("HMGET", jobKey, "parentKey", "deid")
190
+ local missedParentKey = parentAttributes[1]
191
+ if( (type(missedParentKey) == "string") and missedParentKey ~= ""
192
+ and (rcall("EXISTS", missedParentKey) == 1)) then
193
+ local parentDependenciesKey = missedParentKey .. ":dependencies"
194
+ local result = rcall("SREM", parentDependenciesKey, jobKey)
195
+ if result > 0 then
196
+ local pendingDependencies = rcall("SCARD", parentDependenciesKey)
197
+ if pendingDependencies == 0 then
198
+ local parentId = getJobIdFromKey(missedParentKey)
199
+ local parentPrefix = getJobKeyPrefix(missedParentKey, parentId)
200
+ local numRemovedElements = rcall("ZREM", parentPrefix .. "waiting-children", parentId)
201
+ if numRemovedElements == 1 then
202
+ if hard then
203
+ if parentPrefix == baseKey then
204
+ removeParentDependencyKey(missedParentKey, hard, nil, baseKey, nil)
205
+ removeJobKeys(missedParentKey)
206
+ if parentAttributes[2] then
207
+ rcall("DEL", parentPrefix .. "de:" .. parentAttributes[2])
208
+ end
209
+ else
210
+ _moveParentToWait(parentPrefix, parentId)
211
+ end
212
+ else
213
+ _moveParentToWait(parentPrefix, parentId, true)
214
+ end
215
+ end
216
+ end
217
+ return true
218
+ end
219
+ end
220
+ end
221
+ return false
222
+ end
223
+ --[[
224
+ Function to recursively check if there are no locks
225
+ on the jobs to be removed.
226
+ returns:
227
+ boolean
228
+ ]]
229
+ local function isLocked( prefix, jobId, removeChildren)
230
+ local jobKey = prefix .. jobId;
231
+ -- Check if this job is locked
232
+ local lockKey = jobKey .. ':lock'
233
+ local lock = rcall("GET", lockKey)
234
+ if not lock then
235
+ if removeChildren == "1" then
236
+ local dependencies = rcall("SMEMBERS", jobKey .. ":dependencies")
237
+ if (#dependencies > 0) then
238
+ for i, childJobKey in ipairs(dependencies) do
239
+ -- We need to get the jobId for this job.
240
+ local childJobId = getJobIdFromKey(childJobKey)
241
+ local childJobPrefix = getJobKeyPrefix(childJobKey, childJobId)
242
+ local result = isLocked( childJobPrefix, childJobId, removeChildren )
243
+ if result then
244
+ return true
245
+ end
246
+ end
247
+ end
248
+ end
249
+ return false
250
+ end
251
+ return true
252
+ end
253
+ local removeJobChildren
254
+ local removeJobWithChildren
255
+ removeJobChildren = function(prefix, meta, jobKey, options)
256
+ -- Check if this job has children
257
+ -- If so, we are going to try to remove the children recursively in a depth-first way
258
+ -- because if some job is locked, we must exit with an error.
259
+ if not options.ignoreProcessed then
260
+ local processed = rcall("HGETALL", jobKey .. ":processed")
261
+ if #processed > 0 then
262
+ for i = 1, #processed, 2 do
263
+ local childJobId = getJobIdFromKey(processed[i])
264
+ local childJobPrefix = getJobKeyPrefix(processed[i], childJobId)
265
+ removeJobWithChildren(childJobPrefix, meta, childJobId, jobKey, options)
266
+ end
267
+ end
268
+ local failed = rcall("HGETALL", jobKey .. ":failed")
269
+ if #failed > 0 then
270
+ for i = 1, #failed, 2 do
271
+ local childJobId = getJobIdFromKey(failed[i])
272
+ local childJobPrefix = getJobKeyPrefix(failed[i], childJobId)
273
+ removeJobWithChildren(childJobPrefix, meta, childJobId, jobKey, options)
274
+ end
275
+ end
276
+ local unsuccessful = rcall("ZRANGE", jobKey .. ":unsuccessful", 0, -1)
277
+ if #unsuccessful > 0 then
278
+ for i = 1, #unsuccessful, 1 do
279
+ local childJobId = getJobIdFromKey(unsuccessful[i])
280
+ local childJobPrefix = getJobKeyPrefix(unsuccessful[i], childJobId)
281
+ removeJobWithChildren(childJobPrefix, meta, childJobId, jobKey, options)
282
+ end
283
+ end
284
+ end
285
+ local dependencies = rcall("SMEMBERS", jobKey .. ":dependencies")
286
+ if #dependencies > 0 then
287
+ for i, childJobKey in ipairs(dependencies) do
288
+ local childJobId = getJobIdFromKey(childJobKey)
289
+ local childJobPrefix = getJobKeyPrefix(childJobKey, childJobId)
290
+ removeJobWithChildren(childJobPrefix, meta, childJobId, jobKey, options)
291
+ end
292
+ end
293
+ end
294
+ removeJobWithChildren = function(prefix, meta, jobId, parentKey, options)
295
+ local jobKey = prefix .. jobId
296
+ if options.ignoreLocked then
297
+ if isLocked(prefix, jobId) then
298
+ return
299
+ end
300
+ end
301
+ -- Check if job is in the failed zset
302
+ local failedSet = prefix .. "failed"
303
+ if not (options.ignoreProcessed and rcall("ZSCORE", failedSet, jobId)) then
304
+ removeParentDependencyKey(jobKey, false, parentKey, nil)
305
+ if options.removeChildren then
306
+ removeJobChildren(prefix, meta, jobKey, options)
307
+ end
308
+ local prev = removeJobFromAnyState(prefix, jobId)
309
+ removeDeduplicationKey(prefix, jobKey)
310
+ if removeJobKeys(jobKey) > 0 then
311
+ local maxEvents = getOrSetMaxEvents(meta)
312
+ rcall("XADD", prefix .. "events", "MAXLEN", "~", maxEvents, "*", "event", "removed", "jobId", jobId, "prev", prev)
313
+ end
314
+ end
315
+ end
316
+ local prefix = ARGV[1]
317
+ local jobId = ARGV[2]
318
+ local jobKey = KEYS[1]
319
+ local metaKey = KEYS[2]
320
+ local options = {
321
+ removeChildren = "1",
322
+ ignoreProcessed = true,
323
+ ignoreLocked = true
324
+ }
325
+ removeJobChildren(prefix, metaKey, jobKey, options)
326
+ `;
327
+ exports.removeUnprocessedChildren = {
328
+ name: 'removeUnprocessedChildren',
329
+ content,
330
+ keys: 2,
331
+ };
332
+ //# sourceMappingURL=removeUnprocessedChildren-2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"removeUnprocessedChildren-2.js","sourceRoot":"","sources":["../../../src/scripts/removeUnprocessedChildren-2.ts"],"names":[],"mappings":";;;AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkUf,CAAC;AACW,QAAA,yBAAyB,GAAG;IACvC,IAAI,EAAE,2BAA2B;IACjC,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}