class ZTK::RescueRetry

RescueRetry Class

This class contains an exception handling tool, which will allowing retry of all or specific Exceptions based on a set number of attempts to make.

The block is yielded and if a valid exception occurs the block will be re-executed for the set number of attempts.

@example Retry specific exceptions

counter = 0
ZTK::RescueRetry.try(:tries => 3, :on => EOFError) do
  counter += 1
  raise EOFError
end
puts counter.inspect

@example Retry all exceptions

counter = 0
ZTK::RescueRetry.try(:tries => 3) do
  counter += 1
  raise "OMGWTFBBQ"
end
puts counter.inspect

@example Retry exception is skipped because it does not match conditions

counter = 0
ZTK::RescueRetry.try(:tries => 3, :on => EOFError) do
  counter += 1
  raise "OMGWTFBBQ"
end
puts counter.inspect

@author Zachary Patten <zpatten AT jovelabs DOT io>

Public Class Methods

try(options={}, &block) click to toggle source

Rescue and Retry the supplied block.

When no options are supplied, if an Exception is encounter it is surfaced immediately and no retry is performed.

It is advisable to at least leave the delay option at 1. You could optionally set this to 0, but this is generally a bad idea.

@param [Hash] options Configuration options hash. @option options [Integer] :tries (1) How many attempts at executing the

block before we give up and surface the *Exception*.

@option options [Exception,Array<Exception>] :on (Exception) Watch for

specific exceptions instead of performing retry on all exceptions.

@option options [Exception,Array<Exception>] :raise (Exception) Watch

for specific exceptions and do not attempt to retry if they are
raised.

@option options [Float,Integer] :delay (1) How long to sleep for between

each retry.

@option options [Lambda,Proc] :on_retry (nil) A proc or lambda to call

when we catch an exception and retry.

@yield Block should execute the tasks to be rescued and retried if

needed.

@return [Object] The return value of the block.

# File lib/ztk/rescue_retry.rb, line 72
def try(options={}, &block)
  options = Base.build_config({
    :tries => 1,
    :on => Exception,
    :delay => 1,
    :raise => nil
  }, options)

  !block_given? and Base.log_and_raise(options.ui.logger, RescueRetryError, "You must supply a block!")

  raise_exceptions = [options.raise].flatten.compact
  retry_exceptions = [options.on].flatten.compact

  begin
    return block.call

  rescue *retry_exceptions => e

    options.tries -= 1

    if ((options.tries > 0) && !raise_exceptions.include?(e.class))
      options.ui.logger.warn { "Caught #{e.inspect}, we will give it #{options.tries} more tr#{options.tries > 1 ? 'ies' : 'y'}." }

      sleep(options.delay)

      options.on_retry and options.on_retry.call(e)

      retry
    else
      options.ui.logger.fatal { "Caught #{e.inspect} and we have no more tries left! We have to give up now!" }

      raise e
    end
  end

end