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

116 lines
2.4 KiB
Ruby
Raw Permalink Normal View History

2013-09-16 08:49:56 -04:00
module Sidetiq
module Lock
class Redis
include Logging
attr_reader :key, :timeout
2013-09-16 12:27:07 -04:00
def self.all
Sidekiq.redis do |redis|
redis.keys("sidetiq:*:lock").map do |key|
new(key)
end
end
end
2013-09-16 08:49:56 -04:00
def initialize(key, timeout = Sidetiq.config.lock_expire)
2013-09-16 12:27:07 -04:00
@key = extract_key(key)
2013-09-16 08:49:56 -04:00
@timeout = timeout
end
def synchronize
Sidekiq.redis do |redis|
2013-09-16 12:27:07 -04:00
acquired = lock
2013-09-16 08:49:56 -04:00
if acquired
2013-09-16 12:27:07 -04:00
debug "Lock: #{key}"
2013-09-16 08:49:56 -04:00
begin
yield redis
ensure
2013-09-16 12:27:07 -04:00
unlock
2013-09-16 08:49:56 -04:00
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
2013-09-16 12:27:07 -04:00
def meta_data
2013-09-17 04:25:55 -04:00
@meta_data ||= Sidekiq.redis do |redis|
2013-09-16 12:27:07 -04:00
MetaData.from_json(redis.get(key))
end
end
2013-09-16 08:49:56 -04:00
2013-09-16 12:27:07 -04:00
def lock
Sidekiq.redis do |redis|
acquired = false
2013-09-16 08:49:56 -04:00
2013-09-16 12:27:07 -04:00
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
2013-09-16 08:49:56 -04:00
end
end
2013-09-16 12:27:07 -04:00
acquired
end
2013-09-16 08:49:56 -04:00
end
2013-09-16 12:27:07 -04:00
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
2013-09-16 08:49:56 -04:00
end
end
end
end
2013-09-16 12:29:47 -04:00
def unlock!
Sidekiq.redis do |redis|
redis.del(key)
end
end
2013-09-16 12:27:07 -04:00
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
2013-09-16 08:49:56 -04:00
def watch(redis, *args)
redis.watch(*args)
begin
yield
ensure
redis.unwatch
end
end
end
end
end