1
0
Fork 0
mirror of https://github.com/endofunky/sidetiq.git synced 2022-11-09 13:53:30 -05:00
endofunky--sidetiq/lib/sidetiq/lock/redis.rb
2013-09-17 10:42:07 +01:00

115 lines
2.4 KiB
Ruby

module Sidetiq
module Lock
class Redis
include Logging
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 = extract_key(key)
@timeout = timeout
end
def synchronize
Sidekiq.redis do |redis|
acquired = lock
if acquired
debug "Lock: #{key}"
begin
yield redis
ensure
unlock
debug "Unlock: #{key}"
end
end
end
end
def stale?
pttl = meta_data.pttl
# Consider PTTL of -1 (never set) and larger than the
# configured lock_expire as invalid. Locks with timestamps
# older than 1 minute are also considered stale.
pttl < 0 || pttl >= Sidetiq.config.lock_expire ||
meta_data.timestamp < (Sidetiq.clock.gettime.to_i - 60)
end
def meta_data
@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
true
else
false
end
end
end
end
def unlock!
Sidekiq.redis do |redis|
redis.del(key)
end
end
private
def extract_key(key)
case key
when Class
"sidetiq:#{key.name}:lock"
when String
key.match(/sidetiq:(.+):lock/) ? key : "sidetiq:#{key}:lock"
end
end
def watch(redis, *args)
redis.watch(*args)
begin
yield
ensure
redis.unwatch
end
end
end
end
end