Module: Tins::Attempt

Included in:
Object
Defined in:
lib/tins/attempt.rb

Instance Method Summary collapse

Instance Method Details

#attempt(opts = {}, &block) ⇒ Object

Attempts code in block attempts times, sleeping according to sleep between attempts and catching the exception(s) in exception_class.

sleep is either a Proc returning a floating point number for duration as seconds or a Numeric >= 0 or < 0. In the former case this is the duration directly, in the latter case -sleep is the total number of seconds that is slept before giving up, and every attempt is retried after a exponentially increasing duration of seconds.

Iff reraise is true the caught exception is reraised after running out of attempts.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
# File 'lib/tins/attempt.rb', line 14

def attempt(opts = {}, &block)
  sleep           = nil
  exception_class = StandardError
  prev_exception  = nil
  if Numeric === opts
    attempts = opts
  else
    attempts        = opts[:attempts] || 1
    attempts >= 1 or raise ArgumentError, 'at least one attempt is required'
    exception_class = opts[:exception_class] if opts.key?(:exception_class)
    sleep           = interpret_sleep(opts[:sleep], attempts)
    reraise         = opts[:reraise]
  end
  return if attempts <= 0
  count = 0
  if exception_class.nil?
    begin
      count += 1
      if block.call(count, prev_exception)
        return true
      elsif count < attempts
        sleep_duration(sleep, count)
      end
    end until count == attempts
    false
  else
    begin
      count += 1
      block.call(count, prev_exception)
      true
    rescue *exception_class
      if count < attempts
        prev_exception = $!
        sleep_duration(sleep, count)
        retry
      end
      case reraise
      when Proc
        reraise.($!)
      when Exception.class
        raise reraise, "reraised: #{$!.message}"
      when true
        raise $!, "reraised: #{$!.message}"
      else
        false
      end
    end
  end
end