class EM::Hiredis::Lock

Distributed lock built on redis

Public Class Methods

new(redis, key, timeout) click to toggle source
# File lib/em-hiredis/lock.rb, line 7
def initialize(redis, key, timeout)
  @redis, @key, @timeout = redis, key, timeout
  @locked = false
  @expiry = nil
end

Public Instance Methods

acquire() click to toggle source

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
active() click to toggle source

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
clear() click to toggle source

This should not be used in normal operation - force clear

# File lib/em-hiredis/lock.rb, line 56
def clear
  @redis.del(@key)
end
onexpire(&blk) click to toggle source

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
to_s() click to toggle source
# File lib/em-hiredis/lock.rb, line 60
def to_s
  "[lock #{@key}]"
end
unlock() click to toggle source

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