Module: Redis::Lock
- Included in:
- Redis
- Defined in:
- lib/redis/lock.rb
Instance Method Summary collapse
-
#lock(key, timeout = 60, max_attempts = 100) ⇒ Object
Lock a given key.
-
#lock_for_update(key, timeout = 60, max_attempts = 100) ⇒ Object
Lock a given key for updating.
-
#unlock(key) ⇒ Object
Unlock a previously locked key if it has not expired and the current process was the one that locked it.
Instance Method Details
#lock(key, timeout = 60, max_attempts = 100) ⇒ Object
Lock a given key. Optionally takes a timeout and max number of attempts to lock the key before giving up.
Example:
$redis.lock(‘beers_on_the_wall’, 10, 100)
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/redis/lock.rb', line 29 def lock(key, timeout = 60, max_attempts = 100) current_lock_key = lock_key(key) expiration_value = lock_expiration(timeout) attempt_counter = 0 begin if self.setnx(current_lock_key, expiration_value) return true else current_lock = self.get(current_lock_key) if (current_lock.to_s.split('-').first.to_i) < Time.now.to_i compare_value = self.getset(current_lock_key, expiration_value) return true if compare_value == current_lock end end raise "Unable to acquire lock for #{key}." rescue => e if e. == "Unable to acquire lock for #{key}." if attempt_counter == max_attempts raise else attempt_counter += 1 sleep 1 retry end else raise end end end |
#lock_for_update(key, timeout = 60, max_attempts = 100) ⇒ Object
Lock a given key for updating
Example:
$redis = Redis.new lock_for_update(‘beers_on_the_wall’, 20, 1000) do
$redis.decr('beers_on_the_wall')
end
15 16 17 18 19 20 21 |
# File 'lib/redis/lock.rb', line 15 def lock_for_update(key, timeout = 60, max_attempts = 100) if self.lock(key, timeout, max_attempts) response = yield if block_given? self.unlock(key) return response end end |
#unlock(key) ⇒ Object
Unlock a previously locked key if it has not expired and the current process was the one that locked it.
Example:
$redis.unlock(‘beers_on_the_wall’)
66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/redis/lock.rb', line 66 def unlock(key) current_lock_key = lock_key(key) lock_value = self.get(current_lock_key) return true unless lock_value lock_timeout, lock_holder = lock_value.split('-') if (lock_timeout.to_i > Time.now.to_i) && (lock_holder.to_i == Process.pid) self.del(current_lock_key) return true else return false end end |