lib/redis/lock.rb in redis-objects-1.1.0 vs lib/redis/lock.rb in redis-objects-1.2.0

- old
+ new

@@ -28,18 +28,15 @@ # 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) - start = Time.now - gotit = false expiration = nil - while Time.now - start < @options[:timeout] + try_until_timeout do expiration = generate_expiration # Use the expiration as the value of the lock. - gotit = redis.setnx(key, expiration) - break if gotit + break if redis.setnx(key, expiration) # 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? @@ -51,20 +48,14 @@ 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. - if old_expiration < Time.now.to_f - gotit = true - break - end + break if old_expiration < Time.now.to_f end end - - sleep 0.1 end - raise LockTimeout, "Timeout on lock #{key} exceeded #{@options[:timeout]} sec" unless gotit 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 @@ -77,8 +68,23 @@ end end def generate_expiration @options[:expiration].nil? ? 1 : (Time.now + @options[:expiration].to_f + 1).to_f + end + + private + + def try_until_timeout + if @options[:timeout] == 0 + yield + else + start = Time.now + while Time.now - start < @options[:timeout] + yield + sleep 0.1 + end + end + raise LockTimeout, "Timeout on lock #{key} exceeded #{@options[:timeout]} sec" end end end