Class: DoubleRestraint

Inherits:
Object
  • Object
show all
Defined in:
lib/double_restraint.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, timeout:, long_running_timeout:, long_running_limit:, limit: nil, timeout_errors: [Timeout::Error], redis: nil) ⇒ DoubleRestraint

Returns a new instance of DoubleRestraint.

Parameters:

  • name (String, Symbol)

    The name of the restraint.

  • timeout (Numeric)

    The first timeout that will be yielded to the block.

  • long_running_timeout (Numeric)

    The timeout that will be yielded to the block if the block times out the first time it is excuted.

  • long_running_limit (Integer)

    The maximum number of times the block can be run with the long running timeout across all processes.

  • limit (Integer) (defaults to: nil)

    The maximum of number of times the block can be run with the initial timeout across all processes.

  • timeout_errors (Array<Module>) (defaults to: [Timeout::Error])

    List of errors that will be considered a timeout. This needs to be customized depending on what the code in the block could throw to indicate a timeout has occurred.

  • redis (Redis) (defaults to: nil)

    Redis connection to use. If this is not set, the default value set for ‘Restrainer.redis` will be used.



21
22
23
24
25
26
27
28
# File 'lib/double_restraint.rb', line 21

def initialize(name, timeout:, long_running_timeout:, long_running_limit:, limit: nil, timeout_errors: [Timeout::Error], redis: nil)
  @timeout = timeout
  @long_running_timeout = long_running_timeout
  @timeout_errors = Array(timeout_errors)
  limit = -1 if limit.to_i <= 0
  @restrainer = Restrainer.new("DoubleRestrainer(#{name})", limit: limit, redis: redis)
  @long_running_restrainer = Restrainer.new("DoubleRestrainer(#{name}).long_running", limit: long_running_limit, redis: redis)
end

Instance Attribute Details

#long_running_timeoutObject (readonly)

Returns the value of attribute long_running_timeout.



6
7
8
# File 'lib/double_restraint.rb', line 6

def long_running_timeout
  @long_running_timeout
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



6
7
8
# File 'lib/double_restraint.rb', line 6

def timeout
  @timeout
end

Instance Method Details

#default_pool_limitInteger

Get the limit for the default pool. This will return -1 if there is no limit set on that pool.

Returns:

  • (Integer)


72
73
74
# File 'lib/double_restraint.rb', line 72

def default_pool_limit
  @restrainer.limit
end

#default_pool_sizeInteger

Get the current size of the default pool. This can be useful in collecting realtime stats about how the pool is being utilized.

Returns:

  • (Integer)


56
57
58
# File 'lib/double_restraint.rb', line 56

def default_pool_size
  @restrainer.current
end

#execute {|the| ... } ⇒ Object

Execute a block of code. The block will be yielded with the timeout value. If the block raises a timeout error, then it will be called again with the long running timeout. The code in the block must be idempotent since it can be run twice.

Yield Parameters:

  • the (Numeric)

    timeout value to use in the block.

Raises:

  • (Restrainer::ThrottleError)

    if too many concurrent processes are trying to use the restraint.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/double_restraint.rb', line 36

def execute(&block)
  begin
    @restrainer.throttle do
      yield @timeout
    end
  rescue => e
    if @timeout_errors.any? { |error_class| e.is_a?(error_class) }
      @long_running_restrainer.throttle do
        yield @long_running_timeout
      end
    else
      raise e
    end
  end
end

#long_running?(timeout) ⇒ Boolean

Helper method to determine if a timeout represents the long running timeout. Note that the timeout and long running timeouts need to be different values in order for this to work.

Returns:

  • (Boolean)


88
89
90
# File 'lib/double_restraint.rb', line 88

def long_running?(timeout)
  timeout.to_f.round(6) == @long_running_timeout.to_f.round(6)
end

#long_running_pool_limitInteger

Get the limit for the long running pool.

Returns:

  • (Integer)


79
80
81
# File 'lib/double_restraint.rb', line 79

def long_running_pool_limit
  @long_running_restrainer.limit
end

#long_running_pool_sizeInteger

Get the current size of the long running pool. This can be useful in collecting realtime stats about how the pool is being utilized.

Returns:

  • (Integer)


64
65
66
# File 'lib/double_restraint.rb', line 64

def long_running_pool_size
  @long_running_restrainer.current
end