Class: Attempt

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

Overview

The Attempt class encapsulates methods related to multiple attempts at running the same method before actually failing.

Defined Under Namespace

Classes: Warning

Constant Summary collapse

VERSION =

The version of the attempt library.

'0.6.2'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ Attempt

:call-seq:

Attempt.new(**kwargs)

Creates and returns a new Attempt object. The supported keyword options are as follows:

  • tries - The number of attempts to make before giving up. The default is 3.

  • interval - The delay in seconds between each attempt. The default is 60.

  • log - An IO handle or Logger instance where warnings/errors are logged to. The default is nil.

  • increment - The amount to increment the interval between tries. The default is 0.

  • level - The level of exception to be caught. The default is everything, i.e. Exception.

  • warnings - Boolean value that indicates whether or not errors are treated as warnings

    until the maximum number of attempts has been made. The default is true.
    
  • timeout - Boolean value to indicate whether or not to automatically wrap your

    proc in a Timeout/SafeTimeout block. The default is false.
    

Example:

a = Attempt.new(tries: 5, increment: 10, timeout: true)
a.attempt{ http.get("http://something.foo.com") }


67
68
69
70
71
72
73
74
75
# File 'lib/attempt.rb', line 67

def initialize(**options)
  @tries     = options[:tries] || 3         # Reasonable default
  @interval  = options[:interval] || 60     # Reasonable default
  @log       = options[:log]                # Should be an IO handle, if provided
  @increment = options[:increment] || 0     # Should be an integer, if provided
  @timeout   = options[:timeout] || false   # Wrap the code in a timeout block if provided
  @level     = options[:level] || Exception # Level of exception to be caught
  @warnings  = options[:warnings] || true   # Errors are sent to STDERR as warnings if true
end

Instance Attribute Details

#incrementObject

If set, this increments the interval with each failed attempt by that number of seconds.



37
38
39
# File 'lib/attempt.rb', line 37

def increment
  @increment
end

#intervalObject

Number of seconds to wait between attempts. The default is 60.



25
26
27
# File 'lib/attempt.rb', line 25

def interval
  @interval
end

#levelObject

Determines which exception level to check when looking for errors to retry. The default is ‘Exception’ (i.e. all errors).



44
45
46
# File 'lib/attempt.rb', line 44

def level
  @level
end

#logObject

If you provide an IO handle to this option then errors that would have been raised are sent to that handle.



33
34
35
# File 'lib/attempt.rb', line 33

def log
  @log
end

#timeoutObject

If set, the code block is further wrapped in a timeout block.



40
41
42
# File 'lib/attempt.rb', line 40

def timeout
  @timeout
end

#triesObject

Number of attempts to make before failing. The default is 3.



22
23
24
# File 'lib/attempt.rb', line 22

def tries
  @tries
end

#warningsObject

A boolean value that determines whether errors that would have been raised should be sent to STDERR as warnings. The default is true.



29
30
31
# File 'lib/attempt.rb', line 29

def warnings
  @warnings
end

Instance Method Details

#attempt(&block) ⇒ Object

Attempt to perform the operation in the provided block up to tries times, sleeping interval between each try.

You will not typically use this method directly, but the Kernel#attempt method instead.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/attempt.rb', line 83

def attempt(&block)
  count = 1
  begin
    if @timeout
      File::ALT_SEPARATOR ? Timeout.timeout(@timeout, &block) : SafeTimeout.timeout(@timeout, &block)
    else
      yield
    end
  rescue @level => err
    @tries -= 1
    if @tries > 0
      msg = "Error on attempt # #{count}: #{err}; retrying"
      count += 1
      warn Warning, msg if @warnings

      if @log # Accept an IO or Logger object
        @log.respond_to?(:puts) ? @log.puts(msg) : @log.warn(msg)
      end

      @interval += @increment if @increment
      sleep @interval
      retry
    end
    raise
  end
end