bullmq 5.34.6 → 5.34.8

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 (47) hide show
  1. package/dist/cjs/classes/job-scheduler.js +34 -38
  2. package/dist/cjs/classes/job-scheduler.js.map +1 -1
  3. package/dist/cjs/classes/job.js.map +1 -1
  4. package/dist/cjs/classes/scripts.js +35 -5
  5. package/dist/cjs/classes/scripts.js.map +1 -1
  6. package/dist/cjs/commands/addDelayedJob-6.lua +4 -18
  7. package/dist/cjs/commands/{addJobScheduler-2.lua → addJobScheduler-6.lua} +44 -15
  8. package/dist/cjs/commands/includes/addDelayedJob.lua +28 -0
  9. package/dist/cjs/commands/updateJobScheduler-6.lua +61 -0
  10. package/dist/cjs/scripts/addDelayedJob-6.js +74 -64
  11. package/dist/cjs/scripts/addDelayedJob-6.js.map +1 -1
  12. package/dist/cjs/scripts/{addJobScheduler-2.js → addJobScheduler-6.js} +144 -16
  13. package/dist/cjs/scripts/addJobScheduler-6.js.map +1 -0
  14. package/dist/cjs/scripts/index.js +2 -1
  15. package/dist/cjs/scripts/index.js.map +1 -1
  16. package/dist/cjs/scripts/updateJobScheduler-6.js +164 -0
  17. package/dist/cjs/scripts/updateJobScheduler-6.js.map +1 -0
  18. package/dist/cjs/tsconfig-cjs.tsbuildinfo +1 -1
  19. package/dist/cjs/version.js +1 -1
  20. package/dist/esm/classes/job-scheduler.d.ts +1 -1
  21. package/dist/esm/classes/job-scheduler.js +34 -38
  22. package/dist/esm/classes/job-scheduler.js.map +1 -1
  23. package/dist/esm/classes/job.js.map +1 -1
  24. package/dist/esm/classes/scripts.d.ts +3 -3
  25. package/dist/esm/classes/scripts.js +35 -5
  26. package/dist/esm/classes/scripts.js.map +1 -1
  27. package/dist/esm/commands/addDelayedJob-6.lua +4 -18
  28. package/dist/esm/commands/{addJobScheduler-2.lua → addJobScheduler-6.lua} +44 -15
  29. package/dist/esm/commands/includes/addDelayedJob.lua +28 -0
  30. package/dist/esm/commands/updateJobScheduler-6.lua +61 -0
  31. package/dist/esm/scripts/addDelayedJob-6.js +74 -64
  32. package/dist/esm/scripts/addDelayedJob-6.js.map +1 -1
  33. package/dist/esm/scripts/{addJobScheduler-2.js → addJobScheduler-6.js} +144 -16
  34. package/dist/esm/scripts/addJobScheduler-6.js.map +1 -0
  35. package/dist/esm/scripts/index.d.ts +2 -1
  36. package/dist/esm/scripts/index.js +2 -1
  37. package/dist/esm/scripts/index.js.map +1 -1
  38. package/dist/esm/scripts/updateJobScheduler-6.d.ts +5 -0
  39. package/dist/esm/scripts/updateJobScheduler-6.js +161 -0
  40. package/dist/esm/scripts/updateJobScheduler-6.js.map +1 -0
  41. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  42. package/dist/esm/version.d.ts +1 -1
  43. package/dist/esm/version.js +1 -1
  44. package/package.json +1 -1
  45. package/dist/cjs/scripts/addJobScheduler-2.js.map +0 -1
  46. package/dist/esm/scripts/addJobScheduler-2.js.map +0 -1
  47. /package/dist/esm/scripts/{addJobScheduler-2.d.ts → addJobScheduler-6.d.ts} +0 -0
@@ -2,8 +2,12 @@
2
2
  Adds a job scheduler, i.e. a job factory that creates jobs based on a given schedule (repeat options).
3
3
 
4
4
  Input:
5
- KEYS[1] 'repeat' key
6
- KEYS[2] 'delayed' key
5
+ KEYS[1] 'marker',
6
+ KEYS[2] 'meta'
7
+ KEYS[3] 'id'
8
+ KEYS[4] 'delayed'
9
+ KEYS[5] events stream key
10
+ KEYS[6] 'repeat' key
7
11
 
8
12
  ARGV[1] next milliseconds
9
13
  ARGV[2] msgpacked options
@@ -14,27 +18,31 @@
14
18
  [5] every?
15
19
  ARGV[3] jobs scheduler id
16
20
  ARGV[4] Json stringified template data
17
- ARGV[5] mspacked template opts
18
- ARGV[6] prefix key
21
+ ARGV[5] msgpacked template opts
22
+ ARGV[6] msgpacked delayed opts
23
+ ARGV[7] timestamp
24
+ ARGV[8] prefix key
25
+ ARGV[9] producer key
19
26
 
20
27
  Output:
21
- repeatableKey - OK
28
+ next delayed job id - OK
22
29
  ]]
23
30
  local rcall = redis.call
24
- local repeatKey = KEYS[1]
25
- local delayedKey = KEYS[2]
26
-
31
+ local repeatKey = KEYS[6]
32
+ local delayedKey = KEYS[4]
33
+ local timestamp = ARGV[7]
27
34
  local nextMillis = ARGV[1]
28
35
  local jobSchedulerId = ARGV[3]
29
36
  local templateOpts = cmsgpack.unpack(ARGV[5])
30
- local prefixKey = ARGV[6]
37
+ local prefixKey = ARGV[8]
31
38
 
32
39
  -- Includes
40
+ --- @include "includes/addDelayedJob"
41
+ --- @include "includes/getOrSetMaxEvents"
33
42
  --- @include "includes/removeJob"
34
43
 
35
- local function storeRepeatableJob(schedulerId, repeatKey, nextMillis, rawOpts, templateData, templateOpts)
44
+ local function storeRepeatableJob(schedulerId, schedulerKey, repeatKey, nextMillis, opts, templateData, templateOpts)
36
45
  rcall("ZADD", repeatKey, nextMillis, schedulerId)
37
- local opts = cmsgpack.unpack(rawOpts)
38
46
 
39
47
  local optionalValues = {}
40
48
  if opts['tz'] then
@@ -68,17 +76,19 @@ local function storeRepeatableJob(schedulerId, repeatKey, nextMillis, rawOpts, t
68
76
  table.insert(optionalValues, templateData)
69
77
  end
70
78
 
71
- rcall("HMSET", repeatKey .. ":" .. schedulerId, "name", opts['name'],
79
+ rcall("HMSET", schedulerKey, "name", opts['name'],
72
80
  unpack(optionalValues))
73
81
  end
74
82
 
83
+ local schedulerKey = repeatKey .. ":" .. jobSchedulerId
84
+ local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
85
+ local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
86
+
75
87
  -- If we are overriding a repeatable job we must delete the delayed job for
76
88
  -- the next iteration.
77
89
  local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
78
90
  if prevMillis ~= false then
79
91
  local delayedJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
80
- local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
81
- local nextDelayedJobKey = repeatKey .. ":" .. jobSchedulerId .. ":" .. nextMillis
82
92
 
83
93
  if rcall("ZSCORE", delayedKey, delayedJobId) ~= false
84
94
  and (rcall("EXISTS", nextDelayedJobKey) ~= 1
@@ -88,4 +98,23 @@ if prevMillis ~= false then
88
98
  end
89
99
  end
90
100
 
91
- return storeRepeatableJob(jobSchedulerId, repeatKey, nextMillis, ARGV[2], ARGV[4], templateOpts)
101
+ local schedulerOpts = cmsgpack.unpack(ARGV[2])
102
+
103
+ storeRepeatableJob(jobSchedulerId, schedulerKey, repeatKey, nextMillis, schedulerOpts, ARGV[4], templateOpts)
104
+
105
+ local eventsKey = KEYS[5]
106
+ local metaKey = KEYS[2]
107
+ local maxEvents = getOrSetMaxEvents(metaKey)
108
+
109
+ rcall("INCR", KEYS[3])
110
+
111
+ local delayedOpts = cmsgpack.unpack(ARGV[6])
112
+
113
+ addDelayedJob(nextDelayedJobKey, nextDelayedJobId, delayedKey, eventsKey, schedulerOpts['name'], ARGV[4], delayedOpts,
114
+ timestamp, jobSchedulerId, maxEvents, KEYS[1], nil, nil)
115
+
116
+ if ARGV[9] ~= "" then
117
+ rcall("HSET", ARGV[9], "nrjid", nextDelayedJobId)
118
+ end
119
+
120
+ return nextDelayedJobId .. "" -- convert to string
@@ -0,0 +1,28 @@
1
+ --[[
2
+ Adds a delayed job to the queue by doing the following:
3
+ - Creates a new job key with the job data.
4
+ - adds to delayed zset.
5
+ - Emits a global event 'delayed' if the job is delayed.
6
+ ]]
7
+
8
+ -- Includes
9
+ --- @include "addDelayMarkerIfNeeded"
10
+ --- @include "getDelayedScore"
11
+ --- @include "storeJob"
12
+
13
+ local function addDelayedJob(jobIdKey, jobId, delayedKey, eventsKey, name, data, opts, timestamp, repeatJobKey,
14
+ maxEvents, markerKey, parentKey, parentData)
15
+ -- Store the job.
16
+ local delay, priority = storeJob(eventsKey, jobIdKey, jobId, name, data,
17
+ opts, timestamp, parentKey, parentData, repeatJobKey)
18
+
19
+ local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
20
+
21
+ rcall("ZADD", delayedKey, score, jobId)
22
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
23
+ "jobId", jobId, "delay", delayedTimestamp)
24
+
25
+ -- mark that a delayed job is available
26
+ addDelayMarkerIfNeeded(markerKey, delayedKey)
27
+ end
28
+
@@ -0,0 +1,61 @@
1
+ --[[
2
+ Updates a job scheduler and adds next delayed job
3
+
4
+ Input:
5
+ KEYS[1] 'marker',
6
+ KEYS[2] 'meta'
7
+ KEYS[3] 'id'
8
+ KEYS[4] 'delayed'
9
+ KEYS[5] events stream key
10
+ KEYS[6] 'repeat' key
11
+
12
+ ARGV[1] next milliseconds
13
+ ARGV[2] jobs scheduler id
14
+ ARGV[3] msgpacked delayed opts
15
+ ARGV[4] timestamp
16
+ ARGV[5] prefix key
17
+ ARGV[6] producer key
18
+
19
+ Output:
20
+ next delayed job id - OK
21
+ ]]
22
+ local rcall = redis.call
23
+ local repeatKey = KEYS[6]
24
+ local delayedKey = KEYS[4]
25
+ local timestamp = ARGV[4]
26
+ local nextMillis = ARGV[1]
27
+ local jobSchedulerId = ARGV[2]
28
+ local prefixKey = ARGV[5]
29
+
30
+ -- Includes
31
+ --- @include "includes/addDelayedJob"
32
+ --- @include "includes/getOrSetMaxEvents"
33
+
34
+ local schedulerKey = repeatKey .. ":" .. jobSchedulerId
35
+ local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
36
+ local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
37
+
38
+ -- Validate that scheduler exists.
39
+ local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
40
+ if prevMillis ~= false then
41
+ local schedulerAttributes = rcall("HMGET", schedulerKey, "name", "data")
42
+
43
+ rcall("ZADD", repeatKey, nextMillis, jobSchedulerId)
44
+
45
+ local eventsKey = KEYS[5]
46
+ local metaKey = KEYS[2]
47
+ local maxEvents = getOrSetMaxEvents(metaKey)
48
+
49
+ rcall("INCR", KEYS[3])
50
+
51
+ local delayedOpts = cmsgpack.unpack(ARGV[3])
52
+
53
+ addDelayedJob(nextDelayedJobKey, nextDelayedJobId, delayedKey, eventsKey, schedulerAttributes[1],
54
+ schedulerAttributes[2] or "{}", delayedOpts, timestamp, jobSchedulerId, maxEvents, KEYS[1], nil, nil)
55
+
56
+ if ARGV[6] ~= "" then
57
+ rcall("HSET", ARGV[6], "nrjid", nextDelayedJobId)
58
+ end
59
+
60
+ return nextDelayedJobId .. "" -- convert to string
61
+ end
@@ -45,6 +45,13 @@ local repeatJobKey = args[9]
45
45
  local deduplicationKey = args[10]
46
46
  local parentData
47
47
  -- Includes
48
+ --[[
49
+ Adds a delayed job to the queue by doing the following:
50
+ - Creates a new job key with the job data.
51
+ - adds to delayed zset.
52
+ - Emits a global event 'delayed' if the job is delayed.
53
+ ]]
54
+ -- Includes
48
55
  --[[
49
56
  Add delay marker if needed.
50
57
  ]]
@@ -69,29 +76,6 @@ local function addDelayMarkerIfNeeded(markerKey, delayedKey)
69
76
  rcall("ZADD", markerKey, nextTimestamp, "1")
70
77
  end
71
78
  end
72
- --[[
73
- Function to debounce a job.
74
- ]]
75
- local function deduplicateJob(prefixKey, deduplicationOpts, jobId, deduplicationKey, eventsKey, maxEvents)
76
- local deduplicationId = deduplicationOpts and deduplicationOpts['id']
77
- if deduplicationId then
78
- local ttl = deduplicationOpts['ttl']
79
- local deduplicationKeyExists
80
- if ttl then
81
- deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'PX', ttl, 'NX')
82
- else
83
- deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
84
- end
85
- if deduplicationKeyExists then
86
- local currentDebounceJobId = rcall('GET', deduplicationKey)
87
- rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
88
- "debounced", "jobId", currentDebounceJobId, "debounceId", deduplicationId)
89
- rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
90
- "deduplicated", "jobId", currentDebounceJobId, "deduplicationId", deduplicationId)
91
- return currentDebounceJobId
92
- end
93
- end
94
- end
95
79
  --[[
96
80
  Bake in the job id first 12 bits into the timestamp
97
81
  to guarantee correct execution order of delayed jobs
@@ -116,6 +100,71 @@ local function getDelayedScore(delayedKey, timestamp, delay)
116
100
  end
117
101
  return minScore, delayedTimestamp
118
102
  end
103
+ --[[
104
+ Function to store a job
105
+ ]]
106
+ local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
107
+ parentKey, parentData, repeatJobKey)
108
+ local jsonOpts = cjson.encode(opts)
109
+ local delay = opts['delay'] or 0
110
+ local priority = opts['priority'] or 0
111
+ local debounceId = opts['de'] and opts['de']['id']
112
+ local optionalValues = {}
113
+ if parentKey ~= nil then
114
+ table.insert(optionalValues, "parentKey")
115
+ table.insert(optionalValues, parentKey)
116
+ table.insert(optionalValues, "parent")
117
+ table.insert(optionalValues, parentData)
118
+ end
119
+ if repeatJobKey ~= nil then
120
+ table.insert(optionalValues, "rjk")
121
+ table.insert(optionalValues, repeatJobKey)
122
+ end
123
+ if debounceId then
124
+ table.insert(optionalValues, "deid")
125
+ table.insert(optionalValues, debounceId)
126
+ end
127
+ rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
128
+ "timestamp", timestamp, "delay", delay, "priority", priority,
129
+ unpack(optionalValues))
130
+ rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
131
+ return delay, priority
132
+ end
133
+ local function addDelayedJob(jobIdKey, jobId, delayedKey, eventsKey, name, data, opts, timestamp, repeatJobKey,
134
+ maxEvents, markerKey, parentKey, parentData)
135
+ -- Store the job.
136
+ local delay, priority = storeJob(eventsKey, jobIdKey, jobId, name, data,
137
+ opts, timestamp, parentKey, parentData, repeatJobKey)
138
+ local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
139
+ rcall("ZADD", delayedKey, score, jobId)
140
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
141
+ "jobId", jobId, "delay", delayedTimestamp)
142
+ -- mark that a delayed job is available
143
+ addDelayMarkerIfNeeded(markerKey, delayedKey)
144
+ end
145
+ --[[
146
+ Function to debounce a job.
147
+ ]]
148
+ local function deduplicateJob(prefixKey, deduplicationOpts, jobId, deduplicationKey, eventsKey, maxEvents)
149
+ local deduplicationId = deduplicationOpts and deduplicationOpts['id']
150
+ if deduplicationId then
151
+ local ttl = deduplicationOpts['ttl']
152
+ local deduplicationKeyExists
153
+ if ttl then
154
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'PX', ttl, 'NX')
155
+ else
156
+ deduplicationKeyExists = not rcall('SET', deduplicationKey, jobId, 'NX')
157
+ end
158
+ if deduplicationKeyExists then
159
+ local currentDebounceJobId = rcall('GET', deduplicationKey)
160
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
161
+ "debounced", "jobId", currentDebounceJobId, "debounceId", deduplicationId)
162
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
163
+ "deduplicated", "jobId", currentDebounceJobId, "deduplicationId", deduplicationId)
164
+ return currentDebounceJobId
165
+ end
166
+ end
167
+ end
119
168
  --[[
120
169
  Function to get max events value or set by default 10000.
121
170
  ]]
@@ -289,36 +338,6 @@ local function handleDuplicatedJob(jobKey, jobId, currentParentKey, currentParen
289
338
  "duplicated", "jobId", jobId)
290
339
  return jobId .. "" -- convert to string
291
340
  end
292
- --[[
293
- Function to store a job
294
- ]]
295
- local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
296
- parentKey, parentData, repeatJobKey)
297
- local jsonOpts = cjson.encode(opts)
298
- local delay = opts['delay'] or 0
299
- local priority = opts['priority'] or 0
300
- local debounceId = opts['de'] and opts['de']['id']
301
- local optionalValues = {}
302
- if parentKey ~= nil then
303
- table.insert(optionalValues, "parentKey")
304
- table.insert(optionalValues, parentKey)
305
- table.insert(optionalValues, "parent")
306
- table.insert(optionalValues, parentData)
307
- end
308
- if repeatJobKey ~= nil then
309
- table.insert(optionalValues, "rjk")
310
- table.insert(optionalValues, repeatJobKey)
311
- end
312
- if debounceId then
313
- table.insert(optionalValues, "deid")
314
- table.insert(optionalValues, debounceId)
315
- end
316
- rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
317
- "timestamp", timestamp, "delay", delay, "priority", priority,
318
- unpack(optionalValues))
319
- rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
320
- return delay, priority
321
- end
322
341
  if parentKey ~= nil then
323
342
  if rcall("EXISTS", parentKey) ~= 1 then return -5 end
324
343
  parentData = cjson.encode(parent)
@@ -345,17 +364,8 @@ local deduplicationJobId = deduplicateJob(args[1], opts['de'],
345
364
  if deduplicationJobId then
346
365
  return deduplicationJobId
347
366
  end
348
- -- Store the job.
349
- local delay, priority = storeJob(eventsKey, jobIdKey, jobId, args[3], ARGV[2],
350
- opts, timestamp, parentKey, parentData,
351
- repeatJobKey)
352
- local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
353
- rcall("ZADD", delayedKey, score, jobId)
354
- rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
355
- "jobId", jobId, "delay", delayedTimestamp)
356
- -- mark that a delayed job is available
357
- local markerKey = KEYS[1]
358
- addDelayMarkerIfNeeded(markerKey, delayedKey)
367
+ addDelayedJob(jobIdKey, jobId, delayedKey, eventsKey, args[3], ARGV[2], opts, timestamp, repeatJobKey,
368
+ maxEvents, KEYS[1], parentKey, parentData)
359
369
  -- Check if this job is a child of another job, if so add it to the parents dependencies
360
370
  if parentDependenciesKey ~= nil then
361
371
  rcall("SADD", parentDependenciesKey, jobIdKey)
@@ -1 +1 @@
1
- {"version":3,"file":"addDelayedJob-6.js","sourceRoot":"","sources":["../../../src/scripts/addDelayedJob-6.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2Wf,CAAC;AACF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,eAAe;IACrB,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}
1
+ {"version":3,"file":"addDelayedJob-6.js","sourceRoot":"","sources":["../../../src/scripts/addDelayedJob-6.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqXf,CAAC;AACF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,eAAe;IACrB,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}
@@ -1,8 +1,12 @@
1
1
  const content = `--[[
2
2
  Adds a job scheduler, i.e. a job factory that creates jobs based on a given schedule (repeat options).
3
3
  Input:
4
- KEYS[1] 'repeat' key
5
- KEYS[2] 'delayed' key
4
+ KEYS[1] 'marker',
5
+ KEYS[2] 'meta'
6
+ KEYS[3] 'id'
7
+ KEYS[4] 'delayed'
8
+ KEYS[5] events stream key
9
+ KEYS[6] 'repeat' key
6
10
  ARGV[1] next milliseconds
7
11
  ARGV[2] msgpacked options
8
12
  [1] name
@@ -12,19 +16,131 @@ const content = `--[[
12
16
  [5] every?
13
17
  ARGV[3] jobs scheduler id
14
18
  ARGV[4] Json stringified template data
15
- ARGV[5] mspacked template opts
16
- ARGV[6] prefix key
19
+ ARGV[5] msgpacked template opts
20
+ ARGV[6] msgpacked delayed opts
21
+ ARGV[7] timestamp
22
+ ARGV[8] prefix key
23
+ ARGV[9] producer key
17
24
  Output:
18
- repeatableKey - OK
25
+ next delayed job id - OK
19
26
  ]]
20
27
  local rcall = redis.call
21
- local repeatKey = KEYS[1]
22
- local delayedKey = KEYS[2]
28
+ local repeatKey = KEYS[6]
29
+ local delayedKey = KEYS[4]
30
+ local timestamp = ARGV[7]
23
31
  local nextMillis = ARGV[1]
24
32
  local jobSchedulerId = ARGV[3]
25
33
  local templateOpts = cmsgpack.unpack(ARGV[5])
26
- local prefixKey = ARGV[6]
34
+ local prefixKey = ARGV[8]
27
35
  -- Includes
36
+ --[[
37
+ Adds a delayed job to the queue by doing the following:
38
+ - Creates a new job key with the job data.
39
+ - adds to delayed zset.
40
+ - Emits a global event 'delayed' if the job is delayed.
41
+ ]]
42
+ -- Includes
43
+ --[[
44
+ Add delay marker if needed.
45
+ ]]
46
+ -- Includes
47
+ --[[
48
+ Function to return the next delayed job timestamp.
49
+ ]]
50
+ local function getNextDelayedTimestamp(delayedKey)
51
+ local result = rcall("ZRANGE", delayedKey, 0, 0, "WITHSCORES")
52
+ if #result then
53
+ local nextTimestamp = tonumber(result[2])
54
+ if nextTimestamp ~= nil then
55
+ return nextTimestamp / 0x1000
56
+ end
57
+ end
58
+ end
59
+ local function addDelayMarkerIfNeeded(markerKey, delayedKey)
60
+ local nextTimestamp = getNextDelayedTimestamp(delayedKey)
61
+ if nextTimestamp ~= nil then
62
+ -- Replace the score of the marker with the newest known
63
+ -- next timestamp.
64
+ rcall("ZADD", markerKey, nextTimestamp, "1")
65
+ end
66
+ end
67
+ --[[
68
+ Bake in the job id first 12 bits into the timestamp
69
+ to guarantee correct execution order of delayed jobs
70
+ (up to 4096 jobs per given timestamp or 4096 jobs apart per timestamp)
71
+ WARNING: Jobs that are so far apart that they wrap around will cause FIFO to fail
72
+ ]]
73
+ local function getDelayedScore(delayedKey, timestamp, delay)
74
+ local delayedTimestamp = (delay > 0 and (tonumber(timestamp) + delay)) or tonumber(timestamp)
75
+ local minScore = delayedTimestamp * 0x1000
76
+ local maxScore = (delayedTimestamp + 1 ) * 0x1000 - 1
77
+ local result = rcall("ZREVRANGEBYSCORE", delayedKey, maxScore,
78
+ minScore, "WITHSCORES","LIMIT", 0, 1)
79
+ if #result then
80
+ local currentMaxScore = tonumber(result[2])
81
+ if currentMaxScore ~= nil then
82
+ if currentMaxScore >= maxScore then
83
+ return maxScore, delayedTimestamp
84
+ else
85
+ return currentMaxScore + 1, delayedTimestamp
86
+ end
87
+ end
88
+ end
89
+ return minScore, delayedTimestamp
90
+ end
91
+ --[[
92
+ Function to store a job
93
+ ]]
94
+ local function storeJob(eventsKey, jobIdKey, jobId, name, data, opts, timestamp,
95
+ parentKey, parentData, repeatJobKey)
96
+ local jsonOpts = cjson.encode(opts)
97
+ local delay = opts['delay'] or 0
98
+ local priority = opts['priority'] or 0
99
+ local debounceId = opts['de'] and opts['de']['id']
100
+ local optionalValues = {}
101
+ if parentKey ~= nil then
102
+ table.insert(optionalValues, "parentKey")
103
+ table.insert(optionalValues, parentKey)
104
+ table.insert(optionalValues, "parent")
105
+ table.insert(optionalValues, parentData)
106
+ end
107
+ if repeatJobKey ~= nil then
108
+ table.insert(optionalValues, "rjk")
109
+ table.insert(optionalValues, repeatJobKey)
110
+ end
111
+ if debounceId then
112
+ table.insert(optionalValues, "deid")
113
+ table.insert(optionalValues, debounceId)
114
+ end
115
+ rcall("HMSET", jobIdKey, "name", name, "data", data, "opts", jsonOpts,
116
+ "timestamp", timestamp, "delay", delay, "priority", priority,
117
+ unpack(optionalValues))
118
+ rcall("XADD", eventsKey, "*", "event", "added", "jobId", jobId, "name", name)
119
+ return delay, priority
120
+ end
121
+ local function addDelayedJob(jobIdKey, jobId, delayedKey, eventsKey, name, data, opts, timestamp, repeatJobKey,
122
+ maxEvents, markerKey, parentKey, parentData)
123
+ -- Store the job.
124
+ local delay, priority = storeJob(eventsKey, jobIdKey, jobId, name, data,
125
+ opts, timestamp, parentKey, parentData, repeatJobKey)
126
+ local score, delayedTimestamp = getDelayedScore(delayedKey, timestamp, tonumber(delay))
127
+ rcall("ZADD", delayedKey, score, jobId)
128
+ rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "delayed",
129
+ "jobId", jobId, "delay", delayedTimestamp)
130
+ -- mark that a delayed job is available
131
+ addDelayMarkerIfNeeded(markerKey, delayedKey)
132
+ end
133
+ --[[
134
+ Function to get max events value or set by default 10000.
135
+ ]]
136
+ local function getOrSetMaxEvents(metaKey)
137
+ local maxEvents = rcall("HGET", metaKey, "opts.maxLenEvents")
138
+ if not maxEvents then
139
+ maxEvents = 10000
140
+ rcall("HSET", metaKey, "opts.maxLenEvents", maxEvents)
141
+ end
142
+ return maxEvents
143
+ end
28
144
  --[[
29
145
  Function to remove job.
30
146
  ]]
@@ -178,9 +294,8 @@ local function removeJob(jobId, hard, baseKey, shouldRemoveDeduplicationKey)
178
294
  end
179
295
  removeJobKeys(jobKey)
180
296
  end
181
- local function storeRepeatableJob(schedulerId, repeatKey, nextMillis, rawOpts, templateData, templateOpts)
297
+ local function storeRepeatableJob(schedulerId, schedulerKey, repeatKey, nextMillis, opts, templateData, templateOpts)
182
298
  rcall("ZADD", repeatKey, nextMillis, schedulerId)
183
- local opts = cmsgpack.unpack(rawOpts)
184
299
  local optionalValues = {}
185
300
  if opts['tz'] then
186
301
  table.insert(optionalValues, "tz")
@@ -207,16 +322,17 @@ local function storeRepeatableJob(schedulerId, repeatKey, nextMillis, rawOpts, t
207
322
  table.insert(optionalValues, "data")
208
323
  table.insert(optionalValues, templateData)
209
324
  end
210
- rcall("HMSET", repeatKey .. ":" .. schedulerId, "name", opts['name'],
325
+ rcall("HMSET", schedulerKey, "name", opts['name'],
211
326
  unpack(optionalValues))
212
327
  end
328
+ local schedulerKey = repeatKey .. ":" .. jobSchedulerId
329
+ local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
330
+ local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
213
331
  -- If we are overriding a repeatable job we must delete the delayed job for
214
332
  -- the next iteration.
215
333
  local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
216
334
  if prevMillis ~= false then
217
335
  local delayedJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
218
- local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
219
- local nextDelayedJobKey = repeatKey .. ":" .. jobSchedulerId .. ":" .. nextMillis
220
336
  if rcall("ZSCORE", delayedKey, delayedJobId) ~= false
221
337
  and (rcall("EXISTS", nextDelayedJobKey) ~= 1
222
338
  or delayedJobId == nextDelayedJobId) then
@@ -224,11 +340,23 @@ if prevMillis ~= false then
224
340
  rcall("ZREM", delayedKey, delayedJobId)
225
341
  end
226
342
  end
227
- return storeRepeatableJob(jobSchedulerId, repeatKey, nextMillis, ARGV[2], ARGV[4], templateOpts)
343
+ local schedulerOpts = cmsgpack.unpack(ARGV[2])
344
+ storeRepeatableJob(jobSchedulerId, schedulerKey, repeatKey, nextMillis, schedulerOpts, ARGV[4], templateOpts)
345
+ local eventsKey = KEYS[5]
346
+ local metaKey = KEYS[2]
347
+ local maxEvents = getOrSetMaxEvents(metaKey)
348
+ rcall("INCR", KEYS[3])
349
+ local delayedOpts = cmsgpack.unpack(ARGV[6])
350
+ addDelayedJob(nextDelayedJobKey, nextDelayedJobId, delayedKey, eventsKey, schedulerOpts['name'], ARGV[4], delayedOpts,
351
+ timestamp, jobSchedulerId, maxEvents, KEYS[1], nil, nil)
352
+ if ARGV[9] ~= "" then
353
+ rcall("HSET", ARGV[9], "nrjid", nextDelayedJobId)
354
+ end
355
+ return nextDelayedJobId .. "" -- convert to string
228
356
  `;
229
357
  export const addJobScheduler = {
230
358
  name: 'addJobScheduler',
231
359
  content,
232
- keys: 2,
360
+ keys: 6,
233
361
  };
234
- //# sourceMappingURL=addJobScheduler-2.js.map
362
+ //# sourceMappingURL=addJobScheduler-6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addJobScheduler-6.js","sourceRoot":"","sources":["../../../src/scripts/addJobScheduler-6.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmWf,CAAC;AACF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,iBAAiB;IACvB,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}
@@ -1,5 +1,5 @@
1
1
  export * from './addDelayedJob-6';
2
- export * from './addJobScheduler-2';
2
+ export * from './addJobScheduler-6';
3
3
  export * from './addLog-2';
4
4
  export * from './addParentJob-4';
5
5
  export * from './addPrioritizedJob-8';
@@ -41,5 +41,6 @@ export * from './reprocessJob-8';
41
41
  export * from './retryJob-11';
42
42
  export * from './saveStacktrace-1';
43
43
  export * from './updateData-1';
44
+ export * from './updateJobScheduler-6';
44
45
  export * from './updateProgress-3';
45
46
  export * from './updateRepeatableJobMillis-1';
@@ -1,5 +1,5 @@
1
1
  export * from './addDelayedJob-6';
2
- export * from './addJobScheduler-2';
2
+ export * from './addJobScheduler-6';
3
3
  export * from './addLog-2';
4
4
  export * from './addParentJob-4';
5
5
  export * from './addPrioritizedJob-8';
@@ -41,6 +41,7 @@ export * from './reprocessJob-8';
41
41
  export * from './retryJob-11';
42
42
  export * from './saveStacktrace-1';
43
43
  export * from './updateData-1';
44
+ export * from './updateJobScheduler-6';
44
45
  export * from './updateProgress-3';
45
46
  export * from './updateRepeatableJobMillis-1';
46
47
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scripts/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scripts/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const updateJobScheduler: {
2
+ name: string;
3
+ content: string;
4
+ keys: number;
5
+ };