bullmq 5.77.7 → 5.78.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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  <br/>
5
5
  <br/>
6
6
  <p>
7
- The fastest, most reliable, Redis-based distributed queue for Node. <br/>
7
+ The fastest, most reliable, Redis-based distributed queue for Node.js, Python, Rust, and more. <br/>
8
8
  Carefully written for rock solid stability and atomicity.
9
9
  </p>
10
10
  Read the <a href="https://docs.bullmq.io">documentation</a>
@@ -40,7 +40,15 @@ You can find tutorials and news in this blog: https://blog.taskforce.sh/
40
40
 
41
41
  ## 🌐 Language agnostic BullMQ
42
42
 
43
- Do you need to work with BullMQ on platforms other than Node.js? If so, check out the [BullMQ Proxy](https://github.com/taskforcesh/bullmq-proxy)
43
+ BullMQ is available natively in multiple languages:
44
+
45
+ - **Node.js / Bun** — This repository (`npm install bullmq`)
46
+ - **Python** — [`python/`](./python) directory (`pip install bullmq`)
47
+ - **Rust** — [`rust/`](./rust) directory (`cargo add bullmq`)
48
+ - **Elixir** — [`elixir/`](./elixir) directory (`{:bullmq, "~> x.x"}`)
49
+ - **PHP** — [`php/`](./php) directory
50
+
51
+ For other platforms, check out the [BullMQ Proxy](https://github.com/taskforcesh/bullmq-proxy).
44
52
 
45
53
  # Official FrontEnd
46
54
 
@@ -1096,6 +1096,7 @@ class Scripts {
1096
1096
  this.queue.keys.paused,
1097
1097
  this.queue.keys.marker,
1098
1098
  this.queue.keys.events,
1099
+ this.queue.keys.repeat,
1099
1100
  ];
1100
1101
  const args = [
1101
1102
  opts.maxStalledCount,
@@ -10,6 +10,7 @@
10
10
  KEYS[6] 'paused', (LIST)
11
11
  KEYS[7] 'marker'
12
12
  KEYS[8] 'event stream' (STREAM)
13
+ KEYS[9] 'repeat' key
13
14
 
14
15
  ARGV[1] Max stalled job count
15
16
  ARGV[2] queue.toKey('')
@@ -35,6 +36,7 @@ local metaKey = KEYS[5]
35
36
  local pausedKey = KEYS[6]
36
37
  local markerKey = KEYS[7]
37
38
  local eventStreamKey = KEYS[8]
39
+ local repeatKey = KEYS[9]
38
40
  local maxStalledJobCount = tonumber(ARGV[1])
39
41
  local queueKeyPrefix = ARGV[2]
40
42
  local timestamp = ARGV[3]
@@ -74,12 +76,20 @@ if (#stalling > 0) then
74
76
  local stalledCount = rcall("HINCRBY", jobKey, "stc", 1)
75
77
 
76
78
  -- Check if this is a repeatable job by looking at job options
77
- local jobOpts = rcall("HGET", jobKey, "opts")
79
+ local jobSchedulerId = rcall("HGET", jobKey, "rjk")
78
80
  local isRepeatableJob = false
79
- if jobOpts then
80
- local opts = cjson.decode(jobOpts)
81
- if opts and opts["repeat"] then
81
+ if jobSchedulerId then
82
+ local schedulerKey = repeatKey .. ":" .. jobSchedulerId
83
+
84
+ if rcall("EXISTS", schedulerKey) == 1 then
82
85
  isRepeatableJob = true
86
+ else
87
+ -- TODO: remove this check in v6, as it is only needed for legacy repeatable jobs
88
+ -- that stored the scheduler id in the job key but did not create the scheduler hash key
89
+ local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
90
+ if prevMillis then
91
+ isRepeatableJob = true
92
+ end
83
93
  end
84
94
  end
85
95
 
@@ -28,7 +28,7 @@ tslib_1.__exportStar(require("./isJobInList-1"), exports);
28
28
  tslib_1.__exportStar(require("./isMaxed-2"), exports);
29
29
  tslib_1.__exportStar(require("./moveJobFromActiveToWait-9"), exports);
30
30
  tslib_1.__exportStar(require("./moveJobsToWait-8"), exports);
31
- tslib_1.__exportStar(require("./moveStalledJobsToWait-8"), exports);
31
+ tslib_1.__exportStar(require("./moveStalledJobsToWait-9"), exports);
32
32
  tslib_1.__exportStar(require("./moveToActive-11"), exports);
33
33
  tslib_1.__exportStar(require("./moveToDelayed-12"), exports);
34
34
  tslib_1.__exportStar(require("./moveToFinished-14"), exports);
@@ -12,6 +12,7 @@ const content = `--[[
12
12
  KEYS[6] 'paused', (LIST)
13
13
  KEYS[7] 'marker'
14
14
  KEYS[8] 'event stream' (STREAM)
15
+ KEYS[9] 'repeat' key
15
16
  ARGV[1] Max stalled job count
16
17
  ARGV[2] queue.toKey('')
17
18
  ARGV[3] timestamp
@@ -114,6 +115,7 @@ local metaKey = KEYS[5]
114
115
  local pausedKey = KEYS[6]
115
116
  local markerKey = KEYS[7]
116
117
  local eventStreamKey = KEYS[8]
118
+ local repeatKey = KEYS[9]
117
119
  local maxStalledJobCount = tonumber(ARGV[1])
118
120
  local queueKeyPrefix = ARGV[2]
119
121
  local timestamp = ARGV[3]
@@ -145,12 +147,19 @@ if (#stalling > 0) then
145
147
  -- If this job has been stalled too many times, such as if it crashes the worker, then fail it.
146
148
  local stalledCount = rcall("HINCRBY", jobKey, "stc", 1)
147
149
  -- Check if this is a repeatable job by looking at job options
148
- local jobOpts = rcall("HGET", jobKey, "opts")
150
+ local jobSchedulerId = rcall("HGET", jobKey, "rjk")
149
151
  local isRepeatableJob = false
150
- if jobOpts then
151
- local opts = cjson.decode(jobOpts)
152
- if opts and opts["repeat"] then
152
+ if jobSchedulerId then
153
+ local schedulerKey = repeatKey .. ":" .. jobSchedulerId
154
+ if rcall("EXISTS", schedulerKey) == 1 then
153
155
  isRepeatableJob = true
156
+ else
157
+ -- TODO: remove this check in v6, as it is only needed for legacy repeatable jobs
158
+ -- that stored the scheduler id in the job key but did not create the scheduler hash key
159
+ local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
160
+ if prevMillis then
161
+ isRepeatableJob = true
162
+ end
154
163
  end
155
164
  end
156
165
  -- Only fail job if it exceeds stall limit AND is not a repeatable job
@@ -180,5 +189,5 @@ return stalled
180
189
  exports.moveStalledJobsToWait = {
181
190
  name: 'moveStalledJobsToWait',
182
191
  content,
183
- keys: 8,
192
+ keys: 9,
184
193
  };