# class EM::Hiredis::Lock

Cross-process re-entrant lock, backed by redis

### Public Class Methods

new(redis, key, timeout) click to toggle source

    # File lib/em-hiredis/lock.rb, line 15
    def initialize(redis, key, timeout)
      unless timeout.kind_of?(Fixnum) && timeout >= 1
        raise "Timeout must be an integer and >= 1s"
      end
      @redis, @key, @timeout = redis, key, timeout
      @token = SecureRandom.hex
    end

### Public Instance Methods

acquire() click to toggle source

Acquire the lock

This is a re-entrant lock, re-acquiring will succeed and extend the timeout

Returns a deferrable which either succeeds if the lock can be acquired, or fails if it cannot.

    # File lib/em-hiredis/lock.rb, line 28
    def acquire
      df = EM::DefaultDeferrable.new
      @redis.lock_acquire([@key], [@token, @timeout]).callback { |success|
        if (success)
          EM::Hiredis.logger.debug "#{to_s} acquired"

          EM.cancel_timer(@expire_timer) if @expire_timer
          @expire_timer = EM.add_timer(@timeout - 1) {
            EM::Hiredis.logger.debug "#{to_s} Expires in 1s"
            @onexpire.call if @onexpire
          }

          df.succeed
        else
          EM::Hiredis.logger.debug "#{to_s} failed to acquire"
          df.fail("Lock is not available")
        end
      }.errback { |e|
        EM::Hiredis.logger.error "#{to_s} Error acquiring lock #{e}"
        df.fail(e)
      }
      df
    end

clear() click to toggle source

This should not be used in normal operation. Force clear without regard to who owns the lock.

    # File lib/em-hiredis/lock.rb, line 76
    def clear
      EM::Hiredis.logger.warn "#{to_s} Force clearing lock (unsafe)"
      EM.cancel_timer(@expire_timer) if @expire_timer

      @redis.del(@key)
    end

onexpire(&blk) click to toggle source

Register a callback which will be called 1s before the lock expires This is an informational callback, there is no hard guarantee on the timing of its invocation because the callback firing and lock key expiry are handled by different clocks (the client process and redis server respectively)

    # File lib/em-hiredis/lock.rb, line 13
    def onexpire(&blk); @onexpire = blk; end

to_s() click to toggle source

    # File lib/em-hiredis/lock.rb, line 83
    def to_s
      "[lock #{@key}]"
    end

unlock() click to toggle source

Release the lock

Returns a deferrable

    # File lib/em-hiredis/lock.rb, line 55
    def unlock
      EM.cancel_timer(@expire_timer) if @expire_timer

      df = EM::DefaultDeferrable.new
      @redis.lock_release([@key], [@token]).callback { |keys_removed|
        if keys_removed > 0
          EM::Hiredis.logger.debug "#{to_s} released"
          df.succeed
        else
          EM::Hiredis.logger.debug "#{to_s} could not release, not held"
          df.fail("Cannot release a lock we do not hold")
        end
      }.errback { |e|
        EM::Hiredis.logger.error "#{to_s} Error releasing lock #{e}"
        df.fail(e)
      }
      df
    end