Module: Ncio::Support::RetryAction

Defined in:
lib/ncio/support/retry_action.rb

Overview

Provide a method to retry arbitrary code blocks with the ability to rescue certain exceptions and retry rather than failing hard on the exception.

Copied from: https://github.com/puppetlabs/puppetlabs-cloud_provisioner/blob/f6cbac3/lib/puppet/cloudpack/utils.rb

Defined Under Namespace

Classes: RetryException

Class Method Summary collapse

Class Method Details

.retry_action(params = { retry_exceptions: nil, timeout: nil, log: nil }) ⇒ Object

Retry an action, catching exceptions and retrying if the exception has been specified.

rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/ncio/support/retry_action.rb', line 28

def self.retry_action(params = { retry_exceptions: nil, timeout: nil, log: nil })
  # Retry actions for a specified amount of time. This method will allow
  # the final retry to complete even if that extends beyond the timeout
  # period.
  raise RetryException::NoBlockGiven unless block_given?

  raise RetryException::NoTimeoutGiven if params[:timeout].nil?
  params[:retry_exceptions] ||= []

  # Assumes reset_logging! has been called.  This happens in the Ncio::App
  # initialization.
  log = params[:log] || Ncio::Support.log

  start = Time.now
  failures = 0

  # rubocop:disable Lint/RescueException
  begin
    yield

  rescue Exception => e
    # If we were giving exceptions to catch,
    # catch the exceptions we care about and retry.
    # All others fail hard

    raise RetryException::Timeout if timedout?(start, params[:timeout])

    retry_exceptions = params[:retry_exceptions]

    unless retry_exceptions.empty?
      if retry_exceptions.include?(e.class)
        log.warn("Retrying: #{e.class}: #{e}")
      else
        # If the exceptions is not in the list of retry_exceptions
        # re-raise.
        raise e
      end
    end
    # rubocop:enable Lint/RescueException

    failures += 1
    # Increase the amount of time that we sleep after every
    # failed retry attempt.
    sleep(((2**failures) - 1) * 0.1)

    retry
  end
  # rubocop:enable Metrics/PerceivedComplexity, Metrics/MethodLength
end

.timedout?(start, timeout) ⇒ Boolean

Returns:

  • (Boolean)


17
18
19
20
# File 'lib/ncio/support/retry_action.rb', line 17

def self.timedout?(start, timeout)
  return true if timeout.nil?
  (Time.now - start) >= timeout
end