-
-
Notifications
You must be signed in to change notification settings - Fork 277
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
Fix scheduled jobs breaking with new_unique_for method #101
Changes from 6 commits
1a994df
cbe76b4
a94e68e
82ee754
9b08d93
1830400
c062cac
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,14 @@ | ||
module SidekiqUniqueJobs | ||
module Client | ||
module Extensions | ||
def lock_queue_script | ||
<<-LUA | ||
local ret = redis.call('GET', KEYS[1]) | ||
if not ret or ret == 'scheduled' then | ||
return redis.call('SETEX', KEYS[1], ARGV[1], ARGV[2]) | ||
end | ||
LUA | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,11 @@ | ||
require 'sidekiq_unique_jobs/server/middleware' | ||
require 'sidekiq_unique_jobs/connectors' | ||
require 'sidekiq_unique_jobs/client/extensions' | ||
|
||
module SidekiqUniqueJobs | ||
module Client | ||
class Middleware | ||
include Extensions | ||
|
||
def call(worker_class, item, queue, redis_pool = nil) | ||
@worker_class = SidekiqUniqueJobs.worker_class_constantize(worker_class) | ||
@item = item | ||
|
@@ -44,14 +46,14 @@ def storage_method | |
def old_unique_for? | ||
connection do |conn| | ||
conn.watch(payload_hash) | ||
pid = conn.get(payload_hash).to_i | ||
if pid == 1 || (pid == 2 && item['at']) | ||
pid = conn.get(payload_hash) | ||
if pid && (pid != 'scheduled' || item['at']) | ||
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. I'm sorry but 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. Code was a mess already. What I'd like to see is something more in the lines of: def old_unique_for?
connection do |conn|
conn.watch(payload_hash)
pid = conn.get(payload_hash)
return create_lock(conn) unless pid == 'scheduled' || item['at']
conn.unwatch
end
end
def create_lock(conn)
conn.multi do
return clear_exired_lock(conn) unless expires_at > 0
conn.setex(payload_hash, expires_at, item['at'] ? 'scheduled' : item['jid'])
end
end
def clear_expired_lock(conn)
conn.del(payload_hash) # already expired
end Thoughts on that? |
||
conn.unwatch | ||
nil | ||
else | ||
conn.multi do | ||
if expires_at > 0 | ||
conn.setex(payload_hash, expires_at, item['jid']) | ||
conn.setex(payload_hash, expires_at, item['at'] ? 'scheduled' : item['jid']) | ||
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. Why are we not using the 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. Or is the jid not at all interesting until it ends up in the real queue? I have been traveling for 60 hours and feel a little sluggish 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. So we wouldn't normally need the Over all I'm not sure if it's worth caring that much about uniqueness in the scheduled queue, so I may submit a patch later to not have any kind of scheduled uniqueness by default -- but probably we should be as consistent as possible if it is going to be supported? Another to thing to note is using something like "scheduled-#{item['jid']}" will require a substring call in the LUA script - which is more expensive than a direct comparison. |
||
else | ||
conn.del(payload_hash) | ||
end | ||
|
@@ -62,8 +64,18 @@ def old_unique_for? | |
# rubocop:enable MethodLength | ||
|
||
def new_unique_for? | ||
item['at'] ? unique_for_schedule : unique_for_queue | ||
end | ||
|
||
def unique_for_schedule | ||
connection do |conn| | ||
conn.set(payload_hash, 'scheduled', nx: true, ex: expires_at) | ||
end | ||
end | ||
|
||
def unique_for_queue | ||
connection do |conn| | ||
return conn.set(payload_hash, item['jid'], nx: true, ex: expires_at) | ||
conn.eval(lock_queue_script, keys: [payload_hash], argv: [expires_at, item['jid']]) | ||
end | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,8 @@ def payload_hash(item) | |
|
||
def unlock(lock_key, item) | ||
Sidekiq.redis do |con| | ||
con.eval(remove_on_match, keys: [lock_key], argv: [item['jid']]) | ||
val = @parent && @parent.name == 'schedule' ? 'scheduled' : item['jid'] | ||
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. Please create a method for this value and name it appropriately |
||
con.eval(remove_on_match, keys: [lock_key], argv: [val]) | ||
end | ||
end | ||
end | ||
|
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.
This would have to change as well then with a composite key of some sort. Even leaving it as it was with just a simple integer. Not sure what happens in an application with a billion scheduled keys. The jit was needed to prevent unlocking jobs you shouldn't be able to unlock?