bullmq 5.58.7 → 5.58.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.
- package/dist/cjs/classes/job-scheduler.js +22 -24
- package/dist/cjs/classes/job-scheduler.js.map +1 -1
- package/dist/cjs/classes/job.js +6 -2
- package/dist/cjs/classes/job.js.map +1 -1
- package/dist/cjs/classes/queue.js +1 -1
- package/dist/cjs/classes/queue.js.map +1 -1
- package/dist/cjs/classes/scripts.js +37 -11
- package/dist/cjs/classes/scripts.js.map +1 -1
- package/dist/cjs/classes/worker.js +53 -18
- package/dist/cjs/classes/worker.js.map +1 -1
- package/dist/cjs/commands/addJobScheduler-11.lua +81 -25
- package/dist/cjs/commands/addRepeatableJob-2.lua +1 -1
- package/dist/cjs/commands/includes/addJobFromScheduler.lua +5 -3
- package/dist/cjs/commands/includes/getJobSchedulerEveryNextMillis.lua +28 -0
- package/dist/cjs/commands/includes/storeJobScheduler.lua +15 -1
- package/dist/cjs/commands/moveStalledJobsToWait-8.lua +14 -1
- package/dist/cjs/commands/updateJobScheduler-12.lua +50 -14
- package/dist/cjs/enums/error-code.js +2 -0
- package/dist/cjs/enums/error-code.js.map +1 -1
- package/dist/cjs/scripts/addJobScheduler-11.js +108 -25
- package/dist/cjs/scripts/addJobScheduler-11.js.map +1 -1
- package/dist/cjs/scripts/addRepeatableJob-2.js +1 -1
- package/dist/cjs/scripts/moveStalledJobsToWait-8.js +11 -1
- package/dist/cjs/scripts/moveStalledJobsToWait-8.js.map +1 -1
- package/dist/cjs/scripts/updateJobScheduler-12.js +66 -17
- package/dist/cjs/scripts/updateJobScheduler-12.js.map +1 -1
- package/dist/cjs/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/classes/job-scheduler.js +22 -24
- package/dist/esm/classes/job-scheduler.js.map +1 -1
- package/dist/esm/classes/job.js +6 -2
- package/dist/esm/classes/job.js.map +1 -1
- package/dist/esm/classes/queue.d.ts +1 -1
- package/dist/esm/classes/queue.js +1 -1
- package/dist/esm/classes/queue.js.map +1 -1
- package/dist/esm/classes/scripts.d.ts +1 -1
- package/dist/esm/classes/scripts.js +37 -11
- package/dist/esm/classes/scripts.js.map +1 -1
- package/dist/esm/classes/worker.js +53 -18
- package/dist/esm/classes/worker.js.map +1 -1
- package/dist/esm/commands/addJobScheduler-11.lua +81 -25
- package/dist/esm/commands/addRepeatableJob-2.lua +1 -1
- package/dist/esm/commands/includes/addJobFromScheduler.lua +5 -3
- package/dist/esm/commands/includes/getJobSchedulerEveryNextMillis.lua +28 -0
- package/dist/esm/commands/includes/storeJobScheduler.lua +15 -1
- package/dist/esm/commands/moveStalledJobsToWait-8.lua +14 -1
- package/dist/esm/commands/updateJobScheduler-12.lua +50 -14
- package/dist/esm/enums/error-code.d.ts +3 -1
- package/dist/esm/enums/error-code.js +2 -0
- package/dist/esm/enums/error-code.js.map +1 -1
- package/dist/esm/interfaces/job-scheduler-json.d.ts +1 -0
- package/dist/esm/interfaces/repeatable-options.d.ts +1 -0
- package/dist/esm/scripts/addJobScheduler-11.js +108 -25
- package/dist/esm/scripts/addJobScheduler-11.js.map +1 -1
- package/dist/esm/scripts/addRepeatableJob-2.js +1 -1
- package/dist/esm/scripts/moveStalledJobsToWait-8.js +11 -1
- package/dist/esm/scripts/moveStalledJobsToWait-8.js.map +1 -1
- package/dist/esm/scripts/updateJobScheduler-12.js +66 -17
- package/dist/esm/scripts/updateJobScheduler-12.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-code.js","sourceRoot":"","sources":["../../../src/enums/error-code.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"error-code.js","sourceRoot":"","sources":["../../../src/enums/error-code.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,SAYX;AAZD,WAAY,SAAS;IACnB,wDAAgB,CAAA;IAChB,gEAAoB,CAAA;IACpB,4DAAkB,CAAA;IAClB,sEAAuB,CAAA;IACvB,oEAAsB,CAAA;IACtB,gEAAoB,CAAA;IACpB,oFAA8B,CAAA;IAC9B,kFAA6B,CAAA;IAC7B,0EAAyB,CAAA;IACzB,iFAA6B,CAAA;IAC7B,6EAA2B,CAAA;AAC7B,CAAC,EAZW,SAAS,KAAT,SAAS,QAYpB"}
|
|
@@ -16,7 +16,7 @@ const content = `--[[
|
|
|
16
16
|
ARGV[2] msgpacked options
|
|
17
17
|
[1] name
|
|
18
18
|
[2] tz?
|
|
19
|
-
[3]
|
|
19
|
+
[3] pattern?
|
|
20
20
|
[4] endDate?
|
|
21
21
|
[5] every?
|
|
22
22
|
ARGV[3] jobs scheduler id
|
|
@@ -40,7 +40,9 @@ local eventsKey = KEYS[9]
|
|
|
40
40
|
local nextMillis = ARGV[1]
|
|
41
41
|
local jobSchedulerId = ARGV[3]
|
|
42
42
|
local templateOpts = cmsgpack.unpack(ARGV[5])
|
|
43
|
+
local now = tonumber(ARGV[7])
|
|
43
44
|
local prefixKey = ARGV[8]
|
|
45
|
+
local jobOpts = cmsgpack.unpack(ARGV[6])
|
|
44
46
|
-- Includes
|
|
45
47
|
--[[
|
|
46
48
|
Add delay marker if needed.
|
|
@@ -200,10 +202,11 @@ local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed
|
|
|
200
202
|
rcall(pushCmd, targetKey, jobId)
|
|
201
203
|
addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
|
|
202
204
|
end
|
|
203
|
-
local function addJobFromScheduler(jobKey, jobId,
|
|
205
|
+
local function addJobFromScheduler(jobKey, jobId, opts, waitKey, pausedKey, activeKey, metaKey,
|
|
204
206
|
prioritizedKey, priorityCounter, delayedKey, markerKey, eventsKey, name, maxEvents, timestamp,
|
|
205
|
-
data, jobSchedulerId)
|
|
206
|
-
|
|
207
|
+
data, jobSchedulerId, repeatDelay)
|
|
208
|
+
opts['delay'] = repeatDelay
|
|
209
|
+
opts['jobId'] = jobId
|
|
207
210
|
local delay, priority = storeJob(eventsKey, jobKey, jobId, name, data,
|
|
208
211
|
opts, timestamp, nil, nil, jobSchedulerId)
|
|
209
212
|
if delay ~= 0 then
|
|
@@ -374,6 +377,10 @@ local function storeJobScheduler(schedulerId, schedulerKey, repeatKey, nextMilli
|
|
|
374
377
|
table.insert(optionalValues, "pattern")
|
|
375
378
|
table.insert(optionalValues, opts['pattern'])
|
|
376
379
|
end
|
|
380
|
+
if opts['startDate'] then
|
|
381
|
+
table.insert(optionalValues, "startDate")
|
|
382
|
+
table.insert(optionalValues, opts['startDate'])
|
|
383
|
+
end
|
|
377
384
|
if opts['endDate'] then
|
|
378
385
|
table.insert(optionalValues, "endDate")
|
|
379
386
|
table.insert(optionalValues, opts['endDate'])
|
|
@@ -385,6 +392,12 @@ local function storeJobScheduler(schedulerId, schedulerKey, repeatKey, nextMilli
|
|
|
385
392
|
if opts['offset'] then
|
|
386
393
|
table.insert(optionalValues, "offset")
|
|
387
394
|
table.insert(optionalValues, opts['offset'])
|
|
395
|
+
else
|
|
396
|
+
local offset = rcall("HGET", schedulerKey, "offset")
|
|
397
|
+
if offset then
|
|
398
|
+
table.insert(optionalValues, "offset")
|
|
399
|
+
table.insert(optionalValues, tonumber(offset))
|
|
400
|
+
end
|
|
388
401
|
end
|
|
389
402
|
local jsonTemplateOpts = cjson.encode(templateOpts)
|
|
390
403
|
if jsonTemplateOpts and jsonTemplateOpts ~= '{}' then
|
|
@@ -395,15 +408,55 @@ local function storeJobScheduler(schedulerId, schedulerKey, repeatKey, nextMilli
|
|
|
395
408
|
table.insert(optionalValues, "data")
|
|
396
409
|
table.insert(optionalValues, templateData)
|
|
397
410
|
end
|
|
411
|
+
table.insert(optionalValues, "ic")
|
|
412
|
+
table.insert(optionalValues, rcall("HGET", schedulerKey, "ic") or 1)
|
|
398
413
|
rcall("DEL", schedulerKey) -- remove all attributes and then re-insert new ones
|
|
399
|
-
rcall("HMSET", schedulerKey, "name", opts['name'],
|
|
414
|
+
rcall("HMSET", schedulerKey, "name", opts['name'], unpack(optionalValues))
|
|
415
|
+
end
|
|
416
|
+
local function getJobSchedulerEveryNextMillis(prevMillis, every, now, offset, startDate)
|
|
417
|
+
local nextMillis
|
|
418
|
+
if not prevMillis then
|
|
419
|
+
if startDate then
|
|
420
|
+
-- Assuming startDate is passed as milliseconds from JavaScript
|
|
421
|
+
nextMillis = tonumber(startDate)
|
|
422
|
+
nextMillis = nextMillis > now and nextMillis or now
|
|
423
|
+
else
|
|
424
|
+
nextMillis = now
|
|
425
|
+
end
|
|
426
|
+
else
|
|
427
|
+
nextMillis = prevMillis + every
|
|
428
|
+
-- check if we may have missed some iterations
|
|
429
|
+
if nextMillis < now then
|
|
430
|
+
nextMillis = math.floor(now / every) * every + every + (offset or 0)
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
if not offset or offset == 0 then
|
|
434
|
+
local timeSlot = math.floor(nextMillis / every) * every;
|
|
435
|
+
offset = nextMillis - timeSlot;
|
|
436
|
+
end
|
|
437
|
+
-- Return a tuple nextMillis, offset
|
|
438
|
+
return math.floor(nextMillis), math.floor(offset)
|
|
400
439
|
end
|
|
401
440
|
-- If we are overriding a repeatable job we must delete the delayed job for
|
|
402
441
|
-- the next iteration.
|
|
403
442
|
local schedulerKey = repeatKey .. ":" .. jobSchedulerId
|
|
404
|
-
local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
|
|
405
|
-
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
|
406
443
|
local maxEvents = getOrSetMaxEvents(metaKey)
|
|
444
|
+
local templateData = ARGV[4]
|
|
445
|
+
local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
|
|
446
|
+
if prevMillis then
|
|
447
|
+
prevMillis = tonumber(prevMillis)
|
|
448
|
+
end
|
|
449
|
+
local schedulerOpts = cmsgpack.unpack(ARGV[2])
|
|
450
|
+
local every = schedulerOpts['every']
|
|
451
|
+
-- For backwards compatibility we also check the offset from the job itself.
|
|
452
|
+
-- could be removed in future major versions.
|
|
453
|
+
local jobOffset = jobOpts['repeat'] and jobOpts['repeat']['offset'] or 0
|
|
454
|
+
local offset = schedulerOpts['offset'] or jobOffset or 0
|
|
455
|
+
local newOffset = offset
|
|
456
|
+
if every then
|
|
457
|
+
local startDate = schedulerOpts['startDate']
|
|
458
|
+
nextMillis, newOffset = getJobSchedulerEveryNextMillis(prevMillis, every, now, offset, startDate)
|
|
459
|
+
end
|
|
407
460
|
local function removeJobFromScheduler(prefixKey, delayedKey, prioritizedKey, waitKey, pausedKey, jobId,
|
|
408
461
|
metaKey, eventsKey)
|
|
409
462
|
if rcall("ZSCORE", delayedKey, jobId) then
|
|
@@ -426,33 +479,63 @@ local function removeJobFromScheduler(prefixKey, delayedKey, prioritizedKey, wai
|
|
|
426
479
|
end
|
|
427
480
|
return false
|
|
428
481
|
end
|
|
429
|
-
|
|
430
|
-
if not removeJobFromScheduler(prefixKey, delayedKey, prioritizedKey, waitKey, pausedKey,
|
|
431
|
-
nextDelayedJobId, metaKey, eventsKey) then
|
|
432
|
-
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
|
|
433
|
-
"duplicated", "jobId", nextDelayedJobId)
|
|
434
|
-
return nextDelayedJobId .. "" -- convert to string
|
|
435
|
-
end
|
|
436
|
-
end
|
|
437
|
-
local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
|
|
482
|
+
local hadPrevJob = false
|
|
438
483
|
if prevMillis then
|
|
439
484
|
local currentJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
|
|
440
|
-
local
|
|
441
|
-
|
|
442
|
-
|
|
485
|
+
local currentJobKey = schedulerKey .. ":" .. prevMillis
|
|
486
|
+
-- In theory it should always exist the currentJobKey if there is a prevMillis unless something has
|
|
487
|
+
-- gone really wrong.
|
|
488
|
+
if rcall("EXISTS", currentJobKey) == 1 then
|
|
489
|
+
hadPrevJob = removeJobFromScheduler(prefixKey, delayedKey, prioritizedKey, waitKey, pausedKey,
|
|
443
490
|
currentJobId, metaKey, eventsKey)
|
|
444
491
|
end
|
|
445
492
|
end
|
|
446
|
-
|
|
447
|
-
|
|
493
|
+
if hadPrevJob then
|
|
494
|
+
-- The jobs has been removed and we want to replace it, so lets use the same millis.
|
|
495
|
+
nextMillis = prevMillis
|
|
496
|
+
else
|
|
497
|
+
-- Special case where no job was removed, and we need to add the next iteration.
|
|
498
|
+
schedulerOpts['offset'] = newOffset
|
|
499
|
+
end
|
|
500
|
+
-- Check for job ID collision with existing jobs (in any state)
|
|
501
|
+
local jobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
|
502
|
+
local jobKey = prefixKey .. jobId
|
|
503
|
+
-- If there's already a job with this ID, handle the collision
|
|
504
|
+
if rcall("EXISTS", jobKey) == 1 then
|
|
505
|
+
if every then
|
|
506
|
+
-- For 'every' case: try next time slot to avoid collision
|
|
507
|
+
local nextSlotMillis = nextMillis + every
|
|
508
|
+
local nextSlotJobId = "repeat:" .. jobSchedulerId .. ":" .. nextSlotMillis
|
|
509
|
+
local nextSlotJobKey = prefixKey .. nextSlotJobId
|
|
510
|
+
if rcall("EXISTS", nextSlotJobKey) == 0 then
|
|
511
|
+
-- Next slot is free, use it
|
|
512
|
+
nextMillis = nextSlotMillis
|
|
513
|
+
jobId = nextSlotJobId
|
|
514
|
+
else
|
|
515
|
+
-- Next slot also has a job, return error code
|
|
516
|
+
return -11 -- SchedulerJobSlotsBusy
|
|
517
|
+
end
|
|
518
|
+
else
|
|
519
|
+
-- For 'pattern' case: return error code
|
|
520
|
+
return -10 -- SchedulerJobIdCollision
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
local delay = nextMillis - now
|
|
524
|
+
-- Fast Clamp delay to minimum of 0
|
|
525
|
+
if delay < 0 then
|
|
526
|
+
delay = 0
|
|
527
|
+
end
|
|
528
|
+
local nextJobKey = schedulerKey .. ":" .. nextMillis
|
|
529
|
+
-- jobId already calculated above during collision check
|
|
530
|
+
storeJobScheduler(jobSchedulerId, schedulerKey, repeatKey, nextMillis, schedulerOpts, templateData, templateOpts)
|
|
448
531
|
rcall("INCR", KEYS[8])
|
|
449
|
-
addJobFromScheduler(
|
|
532
|
+
addJobFromScheduler(nextJobKey, jobId, jobOpts, waitKey, pausedKey,
|
|
450
533
|
KEYS[11], metaKey, prioritizedKey, KEYS[10], delayedKey, KEYS[7], eventsKey,
|
|
451
|
-
schedulerOpts['name'], maxEvents,
|
|
534
|
+
schedulerOpts['name'], maxEvents, now, templateData, jobSchedulerId, delay)
|
|
452
535
|
if ARGV[9] ~= "" then
|
|
453
|
-
rcall("HSET", ARGV[9], "nrjid",
|
|
536
|
+
rcall("HSET", ARGV[9], "nrjid", jobId)
|
|
454
537
|
end
|
|
455
|
-
return
|
|
538
|
+
return {jobId .. "", delay}
|
|
456
539
|
`;
|
|
457
540
|
export const addJobScheduler = {
|
|
458
541
|
name: 'addJobScheduler',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addJobScheduler-11.js","sourceRoot":"","sources":["../../../src/scripts/addJobScheduler-11.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG
|
|
1
|
+
{"version":3,"file":"addJobScheduler-11.js","sourceRoot":"","sources":["../../../src/scripts/addJobScheduler-11.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0hBf,CAAC;AACF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,iBAAiB;IACvB,OAAO;IACP,IAAI,EAAE,EAAE;CACT,CAAC"}
|
|
@@ -141,7 +141,17 @@ if (#stalling > 0) then
|
|
|
141
141
|
if (removed > 0) then
|
|
142
142
|
-- If this job has been stalled too many times, such as if it crashes the worker, then fail it.
|
|
143
143
|
local stalledCount = rcall("HINCRBY", jobKey, "stc", 1)
|
|
144
|
-
if
|
|
144
|
+
-- Check if this is a repeatable job by looking at job options
|
|
145
|
+
local jobOpts = rcall("HGET", jobKey, "opts")
|
|
146
|
+
local isRepeatableJob = false
|
|
147
|
+
if jobOpts then
|
|
148
|
+
local opts = cjson.decode(jobOpts)
|
|
149
|
+
if opts and opts["repeat"] then
|
|
150
|
+
isRepeatableJob = true
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
-- Only fail job if it exceeds stall limit AND is not a repeatable job
|
|
154
|
+
if stalledCount > maxStalledJobCount and not isRepeatableJob then
|
|
145
155
|
local failedReason = "job stalled more than allowable limit"
|
|
146
156
|
rcall("HSET", jobKey, "defa", failedReason)
|
|
147
157
|
end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moveStalledJobsToWait-8.js","sourceRoot":"","sources":["../../../src/scripts/moveStalledJobsToWait-8.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG
|
|
1
|
+
{"version":3,"file":"moveStalledJobsToWait-8.js","sourceRoot":"","sources":["../../../src/scripts/moveStalledJobsToWait-8.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Kf,CAAC;AACF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,uBAAuB;IAC7B,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}
|
|
@@ -22,19 +22,19 @@ const content = `--[[
|
|
|
22
22
|
ARGV[7] producer id
|
|
23
23
|
Output:
|
|
24
24
|
next delayed job id - OK
|
|
25
|
-
]]
|
|
26
|
-
local rcall = redis.call
|
|
25
|
+
]] local rcall = redis.call
|
|
27
26
|
local repeatKey = KEYS[1]
|
|
28
27
|
local delayedKey = KEYS[2]
|
|
29
28
|
local waitKey = KEYS[3]
|
|
30
29
|
local pausedKey = KEYS[4]
|
|
31
30
|
local metaKey = KEYS[5]
|
|
32
31
|
local prioritizedKey = KEYS[6]
|
|
33
|
-
local nextMillis = ARGV[1]
|
|
32
|
+
local nextMillis = tonumber(ARGV[1])
|
|
34
33
|
local jobSchedulerId = ARGV[2]
|
|
35
|
-
local timestamp = ARGV[5]
|
|
34
|
+
local timestamp = tonumber(ARGV[5])
|
|
36
35
|
local prefixKey = ARGV[6]
|
|
37
36
|
local producerId = ARGV[7]
|
|
37
|
+
local jobOpts = cmsgpack.unpack(ARGV[4])
|
|
38
38
|
-- Includes
|
|
39
39
|
--[[
|
|
40
40
|
Add delay marker if needed.
|
|
@@ -194,10 +194,11 @@ local function addJobInTargetList(targetKey, markerKey, pushCmd, isPausedOrMaxed
|
|
|
194
194
|
rcall(pushCmd, targetKey, jobId)
|
|
195
195
|
addBaseMarkerIfNeeded(markerKey, isPausedOrMaxed)
|
|
196
196
|
end
|
|
197
|
-
local function addJobFromScheduler(jobKey, jobId,
|
|
197
|
+
local function addJobFromScheduler(jobKey, jobId, opts, waitKey, pausedKey, activeKey, metaKey,
|
|
198
198
|
prioritizedKey, priorityCounter, delayedKey, markerKey, eventsKey, name, maxEvents, timestamp,
|
|
199
|
-
data, jobSchedulerId)
|
|
200
|
-
|
|
199
|
+
data, jobSchedulerId, repeatDelay)
|
|
200
|
+
opts['delay'] = repeatDelay
|
|
201
|
+
opts['jobId'] = jobId
|
|
201
202
|
local delay, priority = storeJob(eventsKey, jobKey, jobId, name, data,
|
|
202
203
|
opts, timestamp, nil, nil, jobSchedulerId)
|
|
203
204
|
if delay ~= 0 then
|
|
@@ -227,18 +228,61 @@ local function getOrSetMaxEvents(metaKey)
|
|
|
227
228
|
end
|
|
228
229
|
return maxEvents
|
|
229
230
|
end
|
|
230
|
-
local
|
|
231
|
-
local
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
local function getJobSchedulerEveryNextMillis(prevMillis, every, now, offset, startDate)
|
|
232
|
+
local nextMillis
|
|
233
|
+
if not prevMillis then
|
|
234
|
+
if startDate then
|
|
235
|
+
-- Assuming startDate is passed as milliseconds from JavaScript
|
|
236
|
+
nextMillis = tonumber(startDate)
|
|
237
|
+
nextMillis = nextMillis > now and nextMillis or now
|
|
238
|
+
else
|
|
239
|
+
nextMillis = now
|
|
240
|
+
end
|
|
241
|
+
else
|
|
242
|
+
nextMillis = prevMillis + every
|
|
243
|
+
-- check if we may have missed some iterations
|
|
244
|
+
if nextMillis < now then
|
|
245
|
+
nextMillis = math.floor(now / every) * every + every + (offset or 0)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
if not offset or offset == 0 then
|
|
249
|
+
local timeSlot = math.floor(nextMillis / every) * every;
|
|
250
|
+
offset = nextMillis - timeSlot;
|
|
251
|
+
end
|
|
252
|
+
-- Return a tuple nextMillis, offset
|
|
253
|
+
return math.floor(nextMillis), math.floor(offset)
|
|
254
|
+
end
|
|
234
255
|
local prevMillis = rcall("ZSCORE", repeatKey, jobSchedulerId)
|
|
256
|
+
-- Validate that scheduler exists.
|
|
257
|
+
-- If it does not exist we should not iterate anymore.
|
|
235
258
|
if prevMillis then
|
|
259
|
+
prevMillis = tonumber(prevMillis)
|
|
260
|
+
local schedulerKey = repeatKey .. ":" .. jobSchedulerId
|
|
261
|
+
local schedulerAttributes = rcall("HMGET", schedulerKey, "name", "data", "every", "startDate", "offset")
|
|
262
|
+
local every = tonumber(schedulerAttributes[3])
|
|
263
|
+
local now = tonumber(timestamp)
|
|
264
|
+
-- If every is not found in scheduler attributes, try to get it from job options
|
|
265
|
+
if not every and jobOpts['repeat'] and jobOpts['repeat']['every'] then
|
|
266
|
+
every = tonumber(jobOpts['repeat']['every'])
|
|
267
|
+
end
|
|
268
|
+
if every then
|
|
269
|
+
local startDate = schedulerAttributes[4]
|
|
270
|
+
local jobOptsOffset = jobOpts['repeat'] and jobOpts['repeat']['offset'] or 0
|
|
271
|
+
local offset = schedulerAttributes[5] or jobOptsOffset or 0
|
|
272
|
+
local newOffset
|
|
273
|
+
nextMillis, newOffset = getJobSchedulerEveryNextMillis(prevMillis, every, now, offset, startDate)
|
|
274
|
+
if not offset then
|
|
275
|
+
rcall("HSET", schedulerKey, "offset", newOffset)
|
|
276
|
+
jobOpts['repeat']['offset'] = newOffset
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
local nextDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. nextMillis
|
|
280
|
+
local nextDelayedJobKey = schedulerKey .. ":" .. nextMillis
|
|
236
281
|
local currentDelayedJobId = "repeat:" .. jobSchedulerId .. ":" .. prevMillis
|
|
237
282
|
if producerId == currentDelayedJobId then
|
|
238
283
|
local eventsKey = KEYS[9]
|
|
239
284
|
local maxEvents = getOrSetMaxEvents(metaKey)
|
|
240
285
|
if rcall("EXISTS", nextDelayedJobKey) ~= 1 then
|
|
241
|
-
local schedulerAttributes = rcall("HMGET", schedulerKey, "name", "data")
|
|
242
286
|
rcall("ZADD", repeatKey, nextMillis, jobSchedulerId)
|
|
243
287
|
rcall("HINCRBY", schedulerKey, "ic", 1)
|
|
244
288
|
rcall("INCR", KEYS[8])
|
|
@@ -248,17 +292,22 @@ if prevMillis then
|
|
|
248
292
|
if templateData and templateData ~= '{}' then
|
|
249
293
|
rcall("HSET", schedulerKey, "data", templateData)
|
|
250
294
|
end
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
295
|
+
local delay = nextMillis - now
|
|
296
|
+
-- Fast Clamp delay to minimum of 0
|
|
297
|
+
if delay < 0 then
|
|
298
|
+
delay = 0
|
|
299
|
+
end
|
|
300
|
+
jobOpts["delay"] = delay
|
|
301
|
+
addJobFromScheduler(nextDelayedJobKey, nextDelayedJobId, jobOpts, waitKey, pausedKey, KEYS[12], metaKey,
|
|
302
|
+
prioritizedKey, KEYS[10], delayedKey, KEYS[7], eventsKey, schedulerAttributes[1], maxEvents, ARGV[5],
|
|
303
|
+
templateData or '{}', jobSchedulerId, delay)
|
|
254
304
|
-- TODO: remove this workaround in next breaking change
|
|
255
305
|
if KEYS[11] ~= "" then
|
|
256
306
|
rcall("HSET", KEYS[11], "nrjid", nextDelayedJobId)
|
|
257
307
|
end
|
|
258
308
|
return nextDelayedJobId .. "" -- convert to string
|
|
259
309
|
else
|
|
260
|
-
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event",
|
|
261
|
-
"duplicated", "jobId", nextDelayedJobId)
|
|
310
|
+
rcall("XADD", eventsKey, "MAXLEN", "~", maxEvents, "*", "event", "duplicated", "jobId", nextDelayedJobId)
|
|
262
311
|
end
|
|
263
312
|
end
|
|
264
313
|
end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateJobScheduler-12.js","sourceRoot":"","sources":["../../../src/scripts/updateJobScheduler-12.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG
|
|
1
|
+
{"version":3,"file":"updateJobScheduler-12.js","sourceRoot":"","sources":["../../../src/scripts/updateJobScheduler-12.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyTf,CAAC;AACF,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,oBAAoB;IAC1B,OAAO;IACP,IAAI,EAAE,EAAE;CACT,CAAC"}
|