class TryUntil::Repeatedly

External interface Example: include TryUntil result = Repeatedly.new(Probe.new(Object.new, :to_s))

.attempts(5)
.interval(10)
.delay(10)
.rescues([ ArgumentError, IOError ])
.stop_when(lambda { |response| JSON.parse(response.body)['id'] == 'some_id' })
.log_to($stdout)
.execute

Not all of the above settings are required. These are the default values: attempts = 3 interval = 0 delay = 0 rescues = [] stop_when = lambda { |response| false } log_to = TryUntil::NullPrinter.new

Public Class Methods

new(probe) click to toggle source
# File lib/try_until/repeatedly.rb, line 24
def initialize(probe)
  @probe = probe
  defaults
end

Public Instance Methods

attempts(int_num) click to toggle source
# File lib/try_until/repeatedly.rb, line 29
def attempts(int_num)
  @attempts = int_num
  self
end
configuration() click to toggle source
# File lib/try_until/repeatedly.rb, line 89
def configuration
  { :probe => @probe.to_s, :attempts => @attempts, :interval => @interval,
    :delay => @delay, :rescues => @rescues, :log_to => @log_to }
end
delay(seconds) click to toggle source
# File lib/try_until/repeatedly.rb, line 39
def delay(seconds)
  @delay = seconds
  self
end
execute() click to toggle source

The heart of this gem: This method will repeatedly call '#sample' on the subject and evaluate if the expectated result is returned. In case of errors it will rescue those and continue, provided the type of error is among the ones defined in @rescues.

# File lib/try_until/repeatedly.rb, line 63
def execute
  Kernel.sleep(@delay) if @delay > 0
  count = 1
  condition_met = false
  while count <= @attempts
    begin
      result = @probe.sample
      if @stop_when.call(result)
        condition_met = true
        log_outcome(count, 'CONDITION_MET')
        return result
      end
      log_outcome(count, 'CONDITION_NOT_MET')
    rescue *@rescues => exception
      log_outcome(count, exception.class)
      raise exception, "During final attempt (#{@attempts} configured) target returned #{exception}" if count == @attempts
    ensure
      unless condition_met
        Kernel.sleep @interval if count < @attempts && @interval > 0
        count += 1
      end
    end
  end
  raise "After #{@attempts} attempts, the expected result was not returned!"
end
interval(seconds) click to toggle source
# File lib/try_until/repeatedly.rb, line 34
def interval(seconds)
  @interval = seconds
  self
end
log_to(io) click to toggle source
# File lib/try_until/repeatedly.rb, line 54
def log_to(io)
  @log_to = io
  self
end
rescues(errors) click to toggle source
# File lib/try_until/repeatedly.rb, line 44
def rescues(errors)
  @rescues = errors
  self
end
stop_when(callable) click to toggle source
# File lib/try_until/repeatedly.rb, line 49
def stop_when(callable)
  @stop_when = callable
  self
end

Private Instance Methods

defaults() click to toggle source
# File lib/try_until/repeatedly.rb, line 99
def defaults
  @attempts = 3 unless @attempts
  @interval = 0 unless @interval
  @delay = 0 unless @delay
  @rescues = [] unless @rescues
  @stop_when = lambda { |response| false } unless @stop_when
  @log_to = NullPrinter.new unless @log_to
end
log_outcome(count, outcome) click to toggle source
# File lib/try_until/repeatedly.rb, line 95
def log_outcome(count, outcome)
  @log_to.printf("#{Time.new}|attempt ##{count}|outcome: #{outcome}|#{@attempts - count} attempts left\n")
end