Sha256: 78ee03725452f5e2a95385245877772370a666fdbf463e3c15dfa67e20405f9b

Contents?: true

Size: 1.79 KB

Versions: 3

Compression:

Stored size: 1.79 KB

Contents

# frozen_string_literal: true
require 'redlock'
module Hyrax
  class LockManager
    class UnableToAcquireLockError < StandardError; end

    ##
    # @param [Fixnum] time_to_live How long to hold the lock in milliseconds
    # @param [Fixnum] retry_count How many times to retry to acquire the lock before raising UnableToAcquireLockError
    # @param [Fixnum] retry_delay Maximum wait time in milliseconds before retrying. Wait time is a random value between 0 and retry_delay.
    def initialize(time_to_live, retry_count, retry_delay)
      @ttl = time_to_live
      @retry_count = retry_count
      @retry_delay = retry_delay
    end

    ##
    # Blocks until lock is acquired or timeout.
    def lock(key)
      returned_from_block = nil

      pool.then do |conn|
        client(conn).lock(key, @ttl) do |locked|
          raise UnableToAcquireLockError unless locked
          returned_from_block = yield
        end
      end

      returned_from_block
    rescue ConnectionPool::TimeoutError => err
      Hyrax.logger.error(err.message)
      raise(ConnectionPool::TimeoutError,
            "Failed to aquire a lock from Redlock due to a Redis connection " /
            "timeout: #{err}. If you are using Redis via `ConnectionPool` " /
            "you may wish to increase the pool size.")
    end

    private

    ##
    # @api_private
    def client(conn)
      Redlock::Client.new([conn], retry_count: @retry_count, retry_delay: @retry_delay)
    end

    ##
    # @api private
    #
    # @note support both a ConnectionPool and a raw Redis client for now.
    #   we should drop support for `Redis.current` in 5.0.0.
    #   `#then` supports both options. for a ConnectionPool it will block
    #   until a connection is available.
    def pool
      Hyrax.config.redis_connection || Redis.current
    end
  end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
hyrax-5.0.0.rc1 app/services/hyrax/lock_manager.rb
hyrax-4.0.0 app/services/hyrax/lock_manager.rb
hyrax-4.0.0.rc3 app/services/hyrax/lock_manager.rb