Class: EM::Hiredis::PersistentLock

Inherits:
Object
  • Object
show all
Defined in:
lib/em-hiredis/persistent_lock.rb

Overview

A lock that automatically re-acquires a lock before it loses it

The lock is configured with the following two parameters

:lock_timeout - Specifies how long each lock is acquired for. Setting

this low means that locks need to be re-acquired very often, but a long
timout means that a process that fails without cleaning up after itself
(i.e. without releasing it's underlying lock) will block the anther
process from picking up this lock
replaced for a long while

:retry_interval - Specifies how frequently to retry acquiring the lock in

the case that the lock is held by another process, or there's an error
communicating with redis

Instance Method Summary collapse

Constructor Details

#initialize(redis, key, options = {}) ⇒ PersistentLock

Returns a new instance of PersistentLock.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/em-hiredis/persistent_lock.rb', line 20

def initialize(redis, key, options = {})
  @redis, @key = redis, key
  @timeout = options[:lock_timeout] || 100
  @retry_timeout = options[:retry_interval] || 60
  @lock = EM::Hiredis::Lock.new(redis, key, @timeout)
  @lock.onexpire {
    # When the lock is about to expire, extend (called 1s before expiry)
    acquire()
  }
  @locked = false
  EM.next_tick {
    @running = true
    acquire
  }
end

Instance Method Details

#acquireObject

Acquire the lock (called automatically by initialize)



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/em-hiredis/persistent_lock.rb', line 37

def acquire
  return unless @running

  @lock.acquire.callback {
    if !@locked
      @onlocked.call if @onlocked
      @locked = true
    end
  }.errback { |e|
    if @locked
      # We were previously locked
      @onunlocked.call if @onunlocked
      @locked = false
    end

    if e.kind_of?(EM::Hiredis::RedisError)
      err = e.redis_error
      EM::Hiredis.logger.warn "Unexpected error acquiring #{@lock} #{err}"
    end

    EM.add_timer(@retry_timeout) {
      acquire() unless @locked
    }
  }
end

#locked?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/em-hiredis/persistent_lock.rb', line 73

def locked?
  @locked
end

#onlocked(&blk) ⇒ Object



17
# File 'lib/em-hiredis/persistent_lock.rb', line 17

def onlocked(&blk); @onlocked = blk; self; end

#onunlocked(&blk) ⇒ Object



18
# File 'lib/em-hiredis/persistent_lock.rb', line 18

def onunlocked(&blk); @onunlocked = blk; self; end

#stopObject



63
64
65
66
67
68
69
70
71
# File 'lib/em-hiredis/persistent_lock.rb', line 63

def stop
  @running = false
  if @locked
    # We were previously locked
    @onunlocked.call if @onunlocked
    @locked = false
  end
  @lock.unlock
end