mirror of
https://github.com/endofunky/sidetiq.git
synced 2022-11-09 13:53:30 -05:00

Using plain threads in Sidekiq's Celluloid-based actor model is a little bit like riding a motorcycle without a helmet, so let's try to fit in a bit better.
65 lines
1.2 KiB
Ruby
65 lines
1.2 KiB
Ruby
module Sidetiq
|
|
class Lock # :nodoc: all
|
|
include Logging
|
|
|
|
attr_reader :key, :timeout
|
|
|
|
OWNER = "#{Socket.gethostname}:#{Process.pid}"
|
|
|
|
def initialize(key, timeout = Sidetiq.config.lock_expire)
|
|
@key = key.kind_of?(Class) ? "sidetiq:#{key.name}:lock" : "sidetiq:#{key}:lock"
|
|
@timeout = timeout
|
|
end
|
|
|
|
def synchronize
|
|
Sidekiq.redis do |redis|
|
|
if lock(redis)
|
|
debug "Sidetiq::Clock lock #{key}"
|
|
|
|
begin
|
|
yield redis
|
|
ensure
|
|
unlock(redis)
|
|
debug "Sidetiq::Clock unlock #{key}"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def lock(redis)
|
|
acquired = false
|
|
|
|
watch(redis, key) do
|
|
if !redis.exists(key)
|
|
acquired = !!redis.multi do |multi|
|
|
multi.psetex(key, timeout, OWNER)
|
|
end
|
|
end
|
|
end
|
|
|
|
acquired
|
|
end
|
|
|
|
def unlock(redis)
|
|
watch(redis, key) do
|
|
if redis.get(key) == OWNER
|
|
redis.multi do |multi|
|
|
multi.del(key)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def watch(redis, *args)
|
|
redis.watch(*args)
|
|
|
|
begin
|
|
yield
|
|
ensure
|
|
redis.unwatch
|
|
end
|
|
end
|
|
end
|
|
end
|