Class: DurableCall::Caller

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

Constant Summary collapse

INTERVALS =
{
  :rand => lambda{|_| rand },
  # TODO: progression with the increasing delays between retries
}.freeze
MESSAGES =
{
  :new_retry => 'Retry #%1$i',
  :failed_call => 'Failed to call %1$s on %2$s: %3$s',
  :waiting_before_retry => 'Waiting %1$.2f seconds before retry',
  :retries_error => 'Number of retries exceeded: %1$i',
  :timeout_error => 'Timeout exceeded: %1$.2f',
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(subject, options = {}) ⇒ Caller

Returns a new instance of Caller.



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/durable_call/caller.rb', line 25

def initialize(subject, options={})
  @subject = subject
  { # default options
    :interval => :rand,
    :logger   => nil,
    :retries  => 0,
    :timeout  => nil,
  }.each do |key, value|
    instance_variable_set :"@#{key}", options.key?(key) ? options[key] : value
  end
end

Instance Attribute Details

#subjectObject (readonly)

Returns the value of attribute subject.



23
24
25
# File 'lib/durable_call/caller.rb', line 23

def subject
  @subject
end

Instance Method Details

#call(*args) ⇒ Object



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
63
64
65
66
67
68
69
70
71
# File 'lib/durable_call/caller.rb', line 37

def call(*args)
  Timeout.timeout(@timeout) do
    # we want to return as soon as result will be obtained
    called = false
    result = nil
    (0..@retries).each do |retries_counter|
      # @timeout may be exceeded here and exception will be raised
      begin
        if retries_counter > 0
          # first try isn't "retry"
          log :info, :new_retry, retries_counter
        end
        result = @subject.__send__ *args
        called = true
      rescue => ex
        log :warn, :failed_call, args.inspect, @subject, ex.inspect
        if @interval && retries_counter < @retries
          # interval specified and it's not a last iteration
          sleep_before_retry(retries_counter + 1)
        end
      else
        break
      end
    end
    if called
      result
    else
      log :error, :retries_error, @retries
      raise RetriesError
    end
  end
rescue TimeoutError
  log :error, :timeout_error, @timeout
  raise
end