Class: Redis::Lock
- Inherits:
-
BaseObject
- Object
- BaseObject
- Redis::Lock
- Defined in:
- lib/redis/lock.rb
Overview
Class representing a lock. This functions like a proxy class, in that you can say @object.lock_name { block } to use the lock and also directly, but it is better to use the lock :foo class method in your class to define a lock.
Defined Under Namespace
Classes: LockTimeout
Instance Attribute Summary
Attributes inherited from BaseObject
Instance Method Summary collapse
-
#generate_expiration ⇒ Object
Return expiration in milliseconds.
-
#initialize(key, *args) ⇒ Lock
constructor
A new instance of Lock.
-
#lock ⇒ Object
Get the lock and execute the code block.
- #value ⇒ Object
Methods inherited from BaseObject
#allow_expiration, #as_json, #redis, #set_expiration, #to_hash, #to_json
Methods included from Helpers::CoreCommands
#delete, #exists, #exists?, #expire, #expireat, #marshal, #move, #persist, #rename, #renamenx, #serializer, #ttl, #type, #unmarshal
Constructor Details
#initialize(key, *args) ⇒ Lock
Returns a new instance of Lock.
14 15 16 17 18 19 |
# File 'lib/redis/lock.rb', line 14 def initialize(key, *args) super(key, *args) @options[:timeout] ||= 5 @options[:init] = false if @options[:init].nil? # default :init to false redis.setnx(key, @options[:start]) unless @options[:start] == 0 || @options[:init] === false end |
Instance Method Details
#generate_expiration ⇒ Object
Return expiration in milliseconds
70 71 72 |
# File 'lib/redis/lock.rb', line 70 def generate_expiration ((@options[:expiration].nil? ? 1 : @options[:expiration].to_f) * 1000).to_i end |
#lock ⇒ Object
Get the lock and execute the code block. Any other code that needs the lock (on any server) will spin waiting for the lock up to the :timeout that was specified when the lock was defined.
28 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 59 60 61 62 63 64 65 66 67 |
# File 'lib/redis/lock.rb', line 28 def lock raise ArgumentError, 'Block not given' unless block_given? expiration_ms = generate_expiration expiration_s = expiration_ms / 1000.0 end_time = nil try_until_timeout do end_time = Time.now.to_i + expiration_s # Set a NX record and use the Redis expiration mechanism. # Empty value because the presence of it is enough to lock # `px` only except an Integer in millisecond break if redis.set(key, nil, px: expiration_ms, nx: true) # Backward compatibility code # TODO: remove at the next major release for performance unless @options[:expiration].nil? old_expiration = redis.get(key).to_f # Check it was not an empty string with `zero?` and # the expiration time is passed. if !old_expiration.zero? && old_expiration < Time.now.to_f expiration_ms = generate_expiration expiration_s = expiration_ms / 1000.0 end_time = Time.now.to_i + expiration_s break if redis.set(key, nil, px: expiration_ms) end end end begin yield ensure # We need to be careful when cleaning up the lock key. If we took a really long # time for some reason, and the lock expired, someone else may have it, and # it's not safe for us to remove it. Check how much time has passed since we # wrote the lock key and only delete it if it hasn't expired (or we're not using # lock expiration) if @options[:expiration].nil? || end_time > Time.now.to_f redis.del(key) end end end |
#value ⇒ Object
21 22 23 |
# File 'lib/redis/lock.rb', line 21 def value nil end |