-
Notifications
You must be signed in to change notification settings - Fork 354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf(priority): change priority as a new state #1984
Changes from 12 commits
193b92a
d0b196e
0f87cf8
d42e66c
f386db6
6b77001
0f98015
18b3c1d
499017f
933dc97
5c3db07
e36049c
be80d90
b28fa1b
fb73c30
220e0a4
f535033
0be0c0b
bbf3afb
a5de7da
fab6b3a
527eef5
9020413
acd0fef
3d3a8e3
ab92413
570ef51
6f20687
8fc8fb7
4f069c6
070af22
6d13180
0a53a05
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--[[ | ||
Function priority marker to wait if needed | ||
in order to wake up our workers and to respect priority | ||
order as much as possible | ||
]] | ||
local function addPriorityMarkerIfNeeded(waitKey) | ||
local waitLen = rcall("LLEN", waitKey) | ||
|
||
if waitLen == 0 then | ||
rcall("LPUSH", waitKey, "0:0") | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,39 +17,49 @@ | |
opts - limiter | ||
]] | ||
|
||
-- Includes | ||
--- @include "addJobWithPriority" | ||
|
||
local function moveJobFromWaitToActive(keys, keyPrefix, targetKey, jobId, processedOn, | ||
maxJobs, expireTime, opts) | ||
maxJobs, expireTime, paused, opts) | ||
local jobKey = keyPrefix .. jobId | ||
-- Check if we need to perform rate limiting. | ||
if maxJobs then | ||
local rateLimiterKey = keys[6]; | ||
local jobCounter = tonumber(rcall("INCR", rateLimiterKey)) | ||
|
||
if jobCounter == 1 then | ||
local limiterDuration = opts['limiter'] and opts['limiter']['duration'] | ||
local integerDuration = math.floor(math.abs(limiterDuration)) | ||
rcall("PEXPIRE", rateLimiterKey, integerDuration) | ||
end | ||
|
||
-- check if we passed rate limit, we need to remove the job and return expireTime | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should rename "passed" to "exceeded" here. |
||
if expireTime > 0 then | ||
-- remove from active queue and add back to the wait list | ||
rcall("LREM", keys[2], 1, jobId) | ||
rcall("RPUSH", targetKey, jobId) | ||
|
||
local priority = tonumber(rcall("HGET", jobKey, "priority")) or 0 | ||
|
||
if priority == 0 then | ||
rcall("RPUSH", targetKey, jobId) | ||
else | ||
addJobWithPriority(keys[1], keys[3], priority, paused, jobId) | ||
end | ||
|
||
-- Return when we can process more jobs | ||
return {0, 0, expireTime, 0} | ||
end | ||
|
||
local jobCounter = tonumber(rcall("INCR", rateLimiterKey)) | ||
|
||
if jobCounter == 1 then | ||
local limiterDuration = opts['limiter'] and opts['limiter']['duration'] | ||
local integerDuration = math.floor(math.abs(limiterDuration)) | ||
rcall("PEXPIRE", rateLimiterKey, integerDuration) | ||
end | ||
end | ||
|
||
local jobKey = keyPrefix .. jobId | ||
local lockKey = jobKey .. ':lock' | ||
|
||
-- get a lock | ||
if opts['token'] ~= "0" then | ||
rcall("SET", lockKey, opts['token'], "PX", opts['lockDuration']) | ||
end | ||
|
||
rcall("ZREM", keys[3], jobId) -- remove from priority | ||
rcall("XADD", keys[4], "*", "event", "active", "jobId", jobId, "prev", "waiting") | ||
rcall("HSET", jobKey, "processedOn", processedOn) | ||
rcall("HINCRBY", jobKey, "attemptsMade", 1) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,28 +10,30 @@ | |
--- @include "addJobWithPriority" | ||
|
||
-- Try to get as much as 1000 jobs at once | ||
local function promoteDelayedJobs(delayedKey, targetKey, priorityKey, | ||
eventStreamKey, prefix, timestamp) | ||
local function promoteDelayedJobs(delayedKey, waitKey, targetKey, priorityKey, | ||
eventStreamKey, prefix, timestamp, paused) | ||
local jobs = rcall("ZRANGEBYSCORE", delayedKey, 0, (timestamp + 1) * 0x1000, "LIMIT", 0, 1000) | ||
|
||
if (#jobs > 0) then | ||
rcall("ZREM", delayedKey, unpack(jobs)) | ||
|
||
for _, jobId in ipairs(jobs) do | ||
local jobKey = prefix .. jobId | ||
local priority = | ||
tonumber(rcall("HGET", prefix .. jobId, "priority")) or 0 | ||
tonumber(rcall("HGET", jobKey, "priority")) or 0 | ||
|
||
if priority == 0 then | ||
-- LIFO or FIFO | ||
rcall("LPUSH", targetKey, jobId) | ||
else | ||
addJobWithPriority(priorityKey, priority, targetKey, jobId) | ||
rcall("SET", "DEBUG", "DELAYED") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't forget to remove the debug code 👍 |
||
addJobWithPriority(waitKey, priorityKey, priority, paused, jobId) | ||
end | ||
|
||
-- Emit waiting event | ||
rcall("XADD", eventStreamKey, "*", "event", "waiting", "jobId", | ||
jobId, "prev", "delayed") | ||
rcall("HSET", prefix .. jobId, "delay", 0) | ||
rcall("HSET", jobKey, "delay", 0) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,10 +41,10 @@ local rcall = redis.call | |
--- @include "includes/getTargetQueueList" | ||
--- @include "includes/promoteDelayedJobs" | ||
|
||
local target = getTargetQueueList(KEYS[9], KEYS[1], KEYS[8]) | ||
local target, paused = getTargetQueueList(KEYS[9], KEYS[1], KEYS[8]) | ||
|
||
-- Check if there are delayed jobs that we can move to wait. | ||
promoteDelayedJobs(KEYS[7], target, KEYS[3], KEYS[4], ARGV[1], ARGV[2]) | ||
promoteDelayedJobs(KEYS[7], KEYS[1], target, KEYS[3], KEYS[4], ARGV[1], ARGV[2], paused) | ||
|
||
local opts = cmsgpack.unpack(ARGV[4]) | ||
local maxJobs = tonumber(opts['limiter'] and opts['limiter']['max']) | ||
|
@@ -59,6 +59,9 @@ else | |
return { 0, 0, expireTime, 0 } | ||
end | ||
|
||
-- paused queue | ||
if paused then return {0, 0, 0, 0} end | ||
|
||
-- no job ID, try non-blocking move from wait to active | ||
jobId = rcall("RPOPLPUSH", KEYS[1], KEYS[2]) | ||
end | ||
|
@@ -72,6 +75,9 @@ if jobId then | |
return { 0, 0, expireTime, 0 } | ||
end | ||
|
||
-- paused queue | ||
if paused then return {0, 0, 0, 0} end | ||
|
||
-- Move again since we just got the marker job. | ||
jobId = rcall("RPOPLPUSH", KEYS[1], KEYS[2]) | ||
|
||
|
@@ -85,14 +91,28 @@ if jobId then | |
|
||
if jobId then | ||
-- this script is not really moving, it is preparing the job for processing | ||
return moveJobFromWaitToActive(KEYS, ARGV[1], target, jobId, ARGV[2], maxJobs, expireTime, opts) | ||
return moveJobFromWaitToActive(KEYS, ARGV[1], target, jobId, ARGV[2], maxJobs, expireTime, paused, opts) | ||
else | ||
local prioritizedJob = rcall("ZPOPMIN", KEYS[3]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be refactored. |
||
if #prioritizedJob > 0 then | ||
jobId = prioritizedJob[1] | ||
rcall("LPUSH", KEYS[2], jobId) | ||
return moveJobFromWaitToActive(KEYS, ARGV[1], target, jobId, ARGV[2], maxJobs, expireTime, paused, opts) | ||
end | ||
end | ||
else | ||
local prioritizedJob = rcall("ZPOPMIN", KEYS[3]) | ||
if #prioritizedJob > 0 then | ||
jobId = prioritizedJob[1] | ||
rcall("LPUSH", KEYS[2], jobId) | ||
return moveJobFromWaitToActive(KEYS, ARGV[1], target, jobId, ARGV[2], maxJobs, expireTime, paused, opts) | ||
end | ||
end | ||
|
||
-- Return the timestamp for the next delayed job if any. | ||
local nextTimestamp = getNextDelayedTimestamp(KEYS[7]) | ||
if (nextTimestamp ~= nil) then | ||
return { 0, 0, 0, nextTimestamp} | ||
return { 0, 0, 0, nextTimestamp } | ||
end | ||
|
||
return { 0, 0, 0, 0} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for the comment as the function is descriptive enough