mirror of
https://github.com/endofunky/sidetiq.git
synced 2022-11-09 13:53:30 -05:00
Clean up locking.
This commit is contained in:
parent
fb66884f2a
commit
47f67d1ccc
4 changed files with 65 additions and 36 deletions
|
@ -5,54 +5,79 @@ module Sidetiq
|
|||
|
||||
attr_reader :key, :timeout
|
||||
|
||||
def self.all
|
||||
Sidekiq.redis do |redis|
|
||||
redis.keys("sidetiq:*:lock").map do |key|
|
||||
new(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(key, timeout = Sidetiq.config.lock_expire)
|
||||
@key = key.kind_of?(Class) ? "sidetiq:#{key.name}:lock" : "sidetiq:#{key}:lock"
|
||||
@key = extract_key(key)
|
||||
@timeout = timeout
|
||||
end
|
||||
|
||||
def synchronize
|
||||
Sidekiq.redis do |redis|
|
||||
acquired, meta = lock(redis)
|
||||
acquired = lock
|
||||
|
||||
if acquired
|
||||
debug "Lock: #{meta}"
|
||||
debug "Lock: #{key}"
|
||||
|
||||
begin
|
||||
yield redis
|
||||
ensure
|
||||
unlock(redis)
|
||||
unlock
|
||||
debug "Unlock: #{key}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def meta_data
|
||||
Sidekiq.redis do |redis|
|
||||
MetaData.from_json(redis.get(key))
|
||||
end
|
||||
end
|
||||
|
||||
def lock
|
||||
Sidekiq.redis do |redis|
|
||||
acquired = false
|
||||
|
||||
watch(redis, key) do
|
||||
if !redis.exists(key)
|
||||
acquired = !!redis.multi do |multi|
|
||||
meta = MetaData.for_new_lock(key)
|
||||
multi.psetex(key, timeout, meta.to_json)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
acquired
|
||||
end
|
||||
end
|
||||
|
||||
def unlock
|
||||
Sidekiq.redis do |redis|
|
||||
watch(redis, key) do
|
||||
if meta_data.owner == Sidetiq::Lock::MetaData::OWNER
|
||||
redis.multi do |multi|
|
||||
multi.del(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def lock(redis)
|
||||
acquired, meta = false, nil
|
||||
|
||||
watch(redis, key) do
|
||||
if !redis.exists(key)
|
||||
acquired = !!redis.multi do |multi|
|
||||
meta = MetaData.for_new_lock(key)
|
||||
multi.psetex(key, timeout, meta.to_json)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
[acquired, meta]
|
||||
end
|
||||
|
||||
def unlock(redis)
|
||||
watch(redis, key) do
|
||||
meta = MetaData.from_json(redis.get(key))
|
||||
|
||||
if meta.owner == Sidetiq::Lock::MetaData::OWNER
|
||||
redis.multi do |multi|
|
||||
multi.del(key)
|
||||
end
|
||||
end
|
||||
def extract_key(key)
|
||||
case key
|
||||
when Class
|
||||
"sidetiq:#{key.name}:lock"
|
||||
when String
|
||||
key.match(/sidetiq:(.+):lock/) ? key : "sidetiq:#{key}:lock"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -12,13 +12,7 @@ module Sidetiq
|
|||
end
|
||||
|
||||
app.get "/sidetiq/locks" do
|
||||
Sidekiq.redis do |redis|
|
||||
lock_keys = redis.keys('sidetiq:*:lock')
|
||||
|
||||
@locks = (lock_keys.any? ? redis.mget(*lock_keys) : []).map do |lock|
|
||||
Sidetiq::Lock::MetaData.from_json(lock)
|
||||
end
|
||||
end
|
||||
@locks = Sidetiq::Lock::Redis.all.map(&:meta_data)
|
||||
|
||||
erb File.read(File.join(VIEWS, 'sidetiq_locks.erb'))
|
||||
end
|
||||
|
|
|
@ -21,6 +21,16 @@ class TestLock < Sidetiq::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_all
|
||||
Sidekiq.redis do |redis|
|
||||
redis.set("sidetiq:Foobar:lock", 1)
|
||||
end
|
||||
|
||||
locks = Sidetiq::Lock::Redis.all
|
||||
|
||||
assert_equal "sidetiq:Foobar:lock", locks.first.key
|
||||
end
|
||||
|
||||
def test_lock_sets_correct_meta_data
|
||||
key = SecureRandom.hex(8)
|
||||
internal_key = "sidetiq:#{key}:lock"
|
||||
|
|
|
@ -45,7 +45,7 @@ class TestLockMetaData < Sidetiq::TestCase
|
|||
def test_pttl
|
||||
lock = Sidetiq::Lock::Redis.new("foobar", 1000000)
|
||||
md = Sidekiq.redis do |r|
|
||||
lock.send(:lock, r)
|
||||
lock.lock
|
||||
Sidetiq::Lock::MetaData.from_json(r.get(lock.key))
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue