class MiniScheduler::DistributedMutex
Public Class Methods
new(key, redis)
click to toggle source
# File lib/mini_scheduler/distributed_mutex.rb, line 17 def initialize(key, redis) raise ArgumentError.new('redis argument is nil') if redis.nil? @key = key @redis = redis @mutex = Mutex.new end
redis=(redis)
click to toggle source
# File lib/mini_scheduler/distributed_mutex.rb, line 9 def self.redis=(redis) @default_redis = redis end
synchronize(key, redis = nil, &blk)
click to toggle source
# File lib/mini_scheduler/distributed_mutex.rb, line 13 def self.synchronize(key, redis = nil, &blk) self.new(key, redis || @default_redis).synchronize(&blk) end
Public Instance Methods
synchronize() { || ... }
click to toggle source
NOTE wrapped in mutex to maintain its semantics
# File lib/mini_scheduler/distributed_mutex.rb, line 29 def synchronize @mutex.lock attempts = 0 sleep_duration = BASE_SLEEP_DURATION while !try_to_get_lock sleep(sleep_duration) if sleep_duration < MAX_SLEEP_DURATION sleep_duration = [sleep_duration * 2, MAX_SLEEP_DURATION].min end attempts += 1 raise Timeout if attempts >= MAX_POLLING_ATTEMPTS end yield ensure @redis.del @key @mutex.unlock end
Private Instance Methods
try_to_get_lock()
click to toggle source
# File lib/mini_scheduler/distributed_mutex.rb, line 55 def try_to_get_lock got_lock = false if @redis.setnx @key, Time.now.to_i + 60 @redis.expire @key, 60 got_lock = true else begin @redis.watch @key time = @redis.get @key if time && time.to_i < Time.now.to_i got_lock = @redis.multi do @redis.set @key, Time.now.to_i + 60 end end ensure @redis.unwatch end end got_lock end