Module: Pester

Extended by:
Pester
Included in:
Pester
Defined in:
lib/pester.rb,
lib/pester/config.rb,
lib/pester/version.rb,
lib/pester/behaviors.rb,
lib/pester/environment.rb,
lib/pester/behaviors/sleep.rb

Defined Under Namespace

Modules: Behaviors Classes: Config, Environment

Constant Summary collapse

VERSION =
'1.0.0'

Instance Attribute Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_sym, options = {}, &block) ⇒ Object



91
92
93
94
95
96
97
# File 'lib/pester.rb', line 91

def method_missing(method_sym, options = {}, &block)
  if @environments.key?(method_sym)
    @environments[method_sym]
  else
    super
  end
end

Instance Attribute Details

#environmentsObject

Returns the value of attribute environments.



9
10
11
# File 'lib/pester.rb', line 9

def environments
  @environments
end

Instance Method Details

#configure(&block) ⇒ Object



11
12
13
14
15
16
17
18
# File 'lib/pester.rb', line 11

def configure(&block)
  Config.configure(&block)

  return if Config.environments.nil?

  valid_environments = Config.environments.select { |_, e| e.is_a?(Hash) }
  @environments = Hash[valid_environments.map { |k, e| [k.to_sym, Environment.new(e)] }]
end

#respond_to?(method_sym, options = {}, &block) ⇒ Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/pester.rb', line 87

def respond_to?(method_sym, options = {}, &block)
  super || Config.environments.key?(method_sym)
end

#retry_action(opts = {}, &block) ⇒ Object Also known as: retry

This function executes a block and retries the block depending on which errors were thrown. Retries 4 times by default.

Options:

retry_error_classes       - A single or array of exceptions to retry on. Thrown exceptions not in this list
                            (including parent/sub-classes) will be reraised
retry_error_messages      - A single or array of exception messages to retry on.  If only this options is passed,
                            any exception with a message containing one of these strings will be retried.  If this
                            option is passed along with retry_error_classes, retry will only happen when both the
                            class and the message match the exception.  Strings and regexes are both permitted.
reraise_error_classes     - A single or array of exceptions to always re-raiseon. Thrown exceptions not in
                            this list (including parent/sub-classes) will be retried
max_attempts              - Max number of attempts to retry
delay_interval            - Second interval by which successive attempts will be incremented. A value of 2
                            passed to retry_with_backoff will retry first after 2 seconds, then 4, then 6, et al.
on_retry                  - A Proc to be called on each successive failure, before the next retry
on_max_attempts_exceeded  - A Proc to be called when attempt_num >= max_attempts - 1
logger                    - Where to log the output

Usage:

retry_action(retry_error_classes: [Mysql2::Error]) do
  puts 'trying to remove a directory'
  FileUtils.rm_r(directory)
end


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/pester.rb', line 57

def retry_action(opts = {}, &block)
  merge_defaults(opts)
  if opts[:retry_error_classes] && opts[:reraise_error_classes]
    fail 'You can only have one of retry_error_classes or reraise_error_classes'
  end

  opts[:max_attempts].times do |attempt_num|
    begin
      return yield(block)
    rescue => e
      unless should_retry?(e, opts)
        opts[:logger].warn('Reraising exception from inside retry_action.')
        raise
      end

      if opts[:max_attempts] - 1 > attempt_num
        attempts_left = opts[:max_attempts] - attempt_num - 1
        trace = e.backtrace
        opts[:logger].warn("Failure encountered: #{e}, backing off and trying again #{attempts_left} more times. Trace: #{trace}")
        opts[:on_retry].call(attempt_num, opts[:delay_interval])
      else
        # Careful here because you will get back the return value of the on_max_attempts_exceeded proc!
        return opts[:on_max_attempts_exceeded].call(opts[:logger], opts[:max_attempts], e)
      end
    end
  end

  nil
end

#retry_constant(options = {}, &block) ⇒ Object



20
21
22
# File 'lib/pester.rb', line 20

def retry_constant(options = {}, &block)
  retry_action(options.merge(on_retry: Behaviors::Sleep::Constant), &block)
end

#retry_with_backoff(options = {}, &block) ⇒ Object



24
25
26
# File 'lib/pester.rb', line 24

def retry_with_backoff(options = {}, &block)
  retry_action(options.merge(on_retry: Behaviors::Sleep::Linear), &block)
end

#retry_with_exponential_backoff(options = {}, &block) ⇒ Object



28
29
30
# File 'lib/pester.rb', line 28

def retry_with_exponential_backoff(options = {}, &block)
  retry_action({ delay_interval: 1 }.merge(options).merge(on_retry: Behaviors::Sleep::Exponential), &block)
end