Class: ResilientCall::Retrier

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

Overview

Executes a block with retry, computing the wait between attempts and firing the configured callbacks. Has no knowledge of circuit breakers.

Constant Summary collapse

DEFAULTS =
{
  retries:    3,
  wait:       :exponential,
  base_wait:  0.5,
  max_wait:   30.0,
  jitter:     true,
  on:         [StandardError],
  on_retry:   nil,
  on_failure: nil,
  on_success: nil
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Retrier

Returns a new instance of Retrier.



19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/resilient_call/retrier.rb', line 19

def initialize(options = {})
  opts = DEFAULTS.merge(options)

  @retries    = opts[:retries]
  @wait       = opts[:wait]
  @base_wait  = opts[:base_wait]
  @max_wait   = opts[:max_wait]
  @jitter     = opts[:jitter]
  @on         = Array(opts[:on])
  @on_retry   = opts[:on_retry]
  @on_failure = opts[:on_failure]
  @on_success = opts[:on_success]
end

Instance Method Details

#callObject

Runs the block. Returns its result, or raises RetriesExhaustedError once every attempt has been consumed.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/resilient_call/retrier.rb', line 35

def call
  attempt = 0

  begin
    attempt += 1
    result = yield
    @on_success&.call(result, attempt)
    result
  rescue *@on => err
    if attempt <= @retries
      @on_retry&.call(attempt, err)
      sleep(wait_time(attempt))
      retry
    end

    @on_failure&.call(err)
    # Raised inside the rescue so Ruby populates #cause with `err`.
    raise RetriesExhaustedError.new(attempts: attempt)
  end
end