lib/redis/lock.rb in redis-objects-1.4.0 vs lib/redis/lock.rb in redis-objects-1.4.2
- old
+ new
@@ -31,32 +31,32 @@
end
# 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.
- def lock(&block)
- expiration = nil
+ def lock
+ raise ArgumentError, 'Block not given' unless block_given?
+ expiration = generate_expiration
+ end_time = nil
try_until_timeout do
- expiration = generate_expiration
- # Use the expiration as the value of the lock.
- break if redis.setnx(key, expiration)
+ end_time = Time.now.to_i + expiration
+ # 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, nx: true)
- # Lock is being held. Now check to see if it's expired (if we're using
- # lock expiration).
- # See "Handling Deadlocks" section on http://redis.io/commands/setnx
- if !@options[:expiration].nil?
+ # Backward compatibility code
+ # TODO: remove at the next major release for performance
+ unless @options[:expiration].nil?
old_expiration = redis.get(key).to_f
- if old_expiration < Time.now.to_f
- # If it's expired, use GETSET to update it.
+ # 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 = generate_expiration
- old_expiration = redis.getset(key, expiration).to_f
-
- # Since GETSET returns the old value of the lock, if the old expiration
- # is still in the past, we know no one else has expired the locked
- # and we now have it.
- break if old_expiration < Time.now.to_f
+ end_time = Time.now.to_i + expiration
+ break if redis.set(key, nil, px: expiration)
end
end
end
begin
yield
@@ -64,17 +64,18 @@
# 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? || expiration > Time.now.to_f
+ if @options[:expiration].nil? || end_time > Time.now.to_f
redis.del(key)
end
end
end
+ # Return expiration in milliseconds
def generate_expiration
- @options[:expiration].nil? ? 1 : (Time.now + @options[:expiration].to_f + 1).to_f
+ ((@options[:expiration].nil? ? 1 : @options[:expiration].to_f) * 1000).to_i
end
private
def try_until_timeout