Distributed lock built on redis
# File lib/em-hiredis/lock.rb, line 7 def initialize(redis, key, timeout) @redis, @key, @timeout = redis, key, timeout @locked = false @expiry = nil end
Acquire the lock
It is ok to call acquire again before the lock expires, which will attempt to extend the existing lock.
Returns a deferrable which either succeeds if the lock can be acquired, or fails if it cannot. In both cases the expiry timestamp is returned (for the new lock or for the expired one respectively)
# File lib/em-hiredis/lock.rb, line 18 def acquire df = EM::DefaultDeferrable.new expiry = new_expiry @redis.setnx(@key, expiry).callback { |setnx| if setnx == 1 lock_acquired(expiry) EM::Hiredis.logger.debug "#{to_s} Acquired new lock" df.succeed(expiry) else attempt_to_acquire_existing_lock(df) end }.errback { |e| df.fail(e) } return df end
Lock has been acquired and we're within it's expiry time
# File lib/em-hiredis/lock.rb, line 51 def active @locked && Time.now.to_i < @expiry end
This should not be used in normal operation - force clear
# File lib/em-hiredis/lock.rb, line 56 def clear @redis.del(@key) end
Register an callback which will be called 1s before the lock expires
# File lib/em-hiredis/lock.rb, line 5 def onexpire(&blk); @onexpire = blk; end
# File lib/em-hiredis/lock.rb, line 60 def to_s "[lock #{@key}]" end
Release the lock
Returns a deferrable
# File lib/em-hiredis/lock.rb, line 38 def unlock EM.cancel_timer(@expire_timer) if @expire_timer unless active df = EM::DefaultDeferrable.new df.fail Error.new("Cannot unlock, lock not active") return df end @redis.del(@key) end