class RedisLocks::Mutex
Constants
- NAMESPACE
Public Class Methods
new(key, expires_in: 86400, redis: RedisLocks.redis)
click to toggle source
# File lib/redis_locks/mutex.rb, line 18 def initialize(key, expires_in: 86400, redis: RedisLocks.redis) @key = "#{NAMESPACE}:#{key}" @redis = Connections.ensure_pool(redis) @expires_in = expires_in.to_i raise ArgumentError.new("Invalid expires_in: #{expires_in}") unless expires_in > 0 end
Public Instance Methods
expired?(safety_margin: 0)
click to toggle source
# File lib/redis_locks/mutex.rb, line 75 def expired?(safety_margin: 0) return true unless @expires_at Time.now.utc.to_i + safety_margin >= @expires_at end
lock(expires_at: nil, &block)
click to toggle source
# File lib/redis_locks/mutex.rb, line 26 def lock(expires_at: nil, &block) now = Time.now.utc.to_i locked = false if expires_at expires_at = expires_at.to_i else expires_at = now + @expires_in end @redis.with do |conn| if conn.setnx(@key, expires_at) conn.expire(@key, expires_at - now) @expires_at = expires_at locked = true else # it was locked if (old_value = conn.get(@key)).to_i <= now # lock has expired if conn.getset(@key, expires_at) == old_value @expires_at = expires_at locked = true end end end end return false unless locked return_or_yield(&block) end
lock!(expires_at: nil, &block)
click to toggle source
# File lib/redis_locks/mutex.rb, line 57 def lock!(expires_at: nil, &block) locked = lock(expires_at: expires_at) raise AlreadyLocked.new(@key) unless locked return_or_yield(&block) end
not_expired!(safety_margin: 0)
click to toggle source
# File lib/redis_locks/mutex.rb, line 81 def not_expired!(safety_margin: 0) raise MutexExpired.new(@key) if expired?(safety_margin: safety_margin) end
unlock()
click to toggle source
# File lib/redis_locks/mutex.rb, line 63 def unlock return unless @expires_at # To prevent deleting a lock acquired from another process, only delete # the key if it's still valid, and will be for another 2 seconds if !expired?(safety_margin: 2) @redis.with { |conn| conn.del(@key) } end @expires_at = nil end
Private Instance Methods
return_or_yield() { || ... }
click to toggle source
# File lib/redis_locks/mutex.rb, line 87 def return_or_yield return_value = true if block_given? begin return_value = yield ensure unlock end end return_value end