1 2 3 4 5 6 7 8 9 10 11 12 13 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
# frozen_string_literal: true
module Aws
module Waiters
# @api private
class Waiter
# @api private
RAISE_HANDLER = Seahorse::Client::Plugins::RaiseResponseErrors::Handler
# @api private
def initialize(options = {})
@poller = options[:poller]
@max_attempts = options[:max_attempts]
@delay = options[:delay]
@before_attempt = Array(options[:before_attempt])
@before_wait = Array(options[:before_wait])
end
# @api private
attr_reader :poller
# @return [Integer]
attr_accessor :max_attempts
# @return [Float]
attr_accessor :delay
alias interval delay
alias interval= delay=
# Register a callback that is invoked before every polling attempt.
# Yields the number of attempts made so far.
#
# waiter.before_attempt do |attempts|
# puts "#{attempts} made, about to make attempt #{attempts + 1}"
# end
#
# Throwing `:success` or `:failure` from the given block will stop
# the waiter and return or raise. You can pass a custom message to the
# throw:
#
# # raises Aws::Waiters::Errors::WaiterFailed
# waiter.before_attempt do |attempts|
# throw :failure, 'custom-error-message'
# end
#
# # cause the waiter to stop polling and return
# waiter.before_attempt do |attempts|
# throw :success
# end
#
# @yieldparam [Integer] attempts The number of attempts made.
def before_attempt(&block)
@before_attempt << block if block_given?
end
# Register a callback that is invoked after an attempt but before
# sleeping. Yields the number of attempts made and the previous response.
#
# waiter.before_wait do |attempts, response|
# puts "#{attempts} made"
# puts response.error.inspect
# puts response.data.inspect
# end
#
# Throwing `:success` or `:failure` from the given block will stop
# the waiter and return or raise. You can pass a custom message to the
# throw:
#
# # raises Aws::Waiters::Errors::WaiterFailed
# waiter.before_attempt do |attempts|
# throw :failure, 'custom-error-message'
# end
#
# # cause the waiter to stop polling and return
# waiter.before_attempt do |attempts|
# throw :success
# end
#
#
# @yieldparam [Integer] attempts The number of attempts already made.
# @yieldparam [Seahorse::Client::Response] response The response from
# the previous polling attempts.
def before_wait(&block)
@before_wait << block if block_given?
end
# @option options [Client] :client
# @option options [Hash] :params
def wait(options)
catch(:success) do
failure_msg = catch(:failure) do
return poll(options)
end
raise Errors::WaiterFailed.new(failure_msg || 'waiter failed')
end || true
end
private
def poll(options)
n = 0
loop do
trigger_before_attempt(n)
state, resp = @poller.call(options)
n += 1
case state
when :retry
when :success then return resp
when :failure then raise Errors::FailureStateError.new(resp)
when :error then raise Errors::UnexpectedError.new(resp.error)
end
raise Errors::TooManyAttemptsError.new(n) if n == @max_attempts
trigger_before_wait(n, resp)
sleep(@delay)
end
end
def trigger_before_attempt(attempts)
@before_attempt.each { |block| block.call(attempts) }
end
def trigger_before_wait(attempts, response)
@before_wait.each { |block| block.call(attempts, response) }
end
end
end
end
|