Class: Distlock::Redis::ExclusiveLock
- Inherits:
-
Object
- Object
- Distlock::Redis::ExclusiveLock
- Includes:
- Common
- Defined in:
- lib/distlock/redis/exclusive_lock.rb
Overview
see here for retry count based example - github.com/PatrickTulskie/redis-lock/blob/master/lib/redis/lock.rb
Constant Summary collapse
- DEFAULT_LEASE_FOR =
5 mins
300
- DEFAULT_RETRY_FOR =
1 min
60
- DEFAULT_RETRY_IN =
1 sec
1
Instance Method Summary collapse
- #generate_lock_value(lease_for = DEFAULT_LEASE_FOR, id = Process.pid) ⇒ Object
-
#initialize(options = {}) ⇒ ExclusiveLock
constructor
A new instance of ExclusiveLock.
- #lock(path, lease_for = DEFAULT_LEASE_FOR, retry_for = DEFAULT_RETRY_FOR) ⇒ Object
- #my_lock ⇒ Object
- #unlock ⇒ Object
- #with_lock(path = '/distlock/redis/exclusive_lock/default', lease_for = DEFAULT_LEASE_FOR, retry_for = DEFAULT_RETRY_FOR) ⇒ Object
Methods included from Common
Constructor Details
#initialize(options = {}) ⇒ ExclusiveLock
Returns a new instance of ExclusiveLock.
15 16 |
# File 'lib/distlock/redis/exclusive_lock.rb', line 15 def initialize(={}) end |
Instance Method Details
#generate_lock_value(lease_for = DEFAULT_LEASE_FOR, id = Process.pid) ⇒ Object
66 67 68 |
# File 'lib/distlock/redis/exclusive_lock.rb', line 66 def generate_lock_value(lease_for=DEFAULT_LEASE_FOR, id=Process.pid) "#{Time.now.to_i + lease_for + 1}-#{id}" end |
#lock(path, lease_for = DEFAULT_LEASE_FOR, retry_for = DEFAULT_RETRY_FOR) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/distlock/redis/exclusive_lock.rb', line 22 def lock(path, lease_for = DEFAULT_LEASE_FOR, retry_for = DEFAULT_RETRY_FOR) now = Time.now retry_until = now + retry_for @my_lock = path lock_value = generate_lock_value(lease_for) while Time.now < retry_until if redis.setnx(path, lock_value) logger.debug "acquired lock (setnx) - #{my_lock}, #{lock_value}" return true end current_lock = redis.get(my_lock) if (current_lock.to_s.split('-').first.to_i) < Time.now.to_i updated_lock = redis.getset(my_lock, lock_value) if updated_lock == current_lock logger.debug "acquired lock (getset) - #{my_lock}, #{lock_value}" return true end end sleep DEFAULT_RETRY_IN end raise LockError.new("failed to get the lock") end |
#my_lock ⇒ Object
18 19 20 |
# File 'lib/distlock/redis/exclusive_lock.rb', line 18 def my_lock @my_lock end |
#unlock ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/distlock/redis/exclusive_lock.rb', line 51 def unlock lock_value = redis.get(my_lock) unless lock_value logger.debug "no lock to release" return true end lease_expires, owner = lock_value.split('-') if (lease_expires.to_i > Time.now.to_i) && (owner.to_i == Process.pid) redis.del(my_lock) logger.debug "released lock - #{my_lock}, #{lock_value}" return true end end |
#with_lock(path = '/distlock/redis/exclusive_lock/default', lease_for = DEFAULT_LEASE_FOR, retry_for = DEFAULT_RETRY_FOR) ⇒ Object
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/distlock/redis/exclusive_lock.rb', line 70 def with_lock(path='/distlock/redis/exclusive_lock/default', lease_for=DEFAULT_LEASE_FOR, retry_for=DEFAULT_RETRY_FOR) begin lock(path, lease_for, retry_for) yield if block_given? ensure # TODO - store lock path so we don't need to pass it here # unlock(path) unlock end end |