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
|
# frozen_string_literal: true
module Aws
module Waiters
# Polls a single API operation inspecting the response data and/or error
# for states matching one of its acceptors.
# @api private
class Poller
# @api private
RAISE_HANDLER = Seahorse::Client::Plugins::RaiseResponseErrors::Handler
# @option options [required, String] :operation_name
# @option options [required, Array<Hash>] :acceptors
# @api private
def initialize(options = {})
@operation_name = options.fetch(:operation_name)
@acceptors = options.fetch(:acceptors)
end
# @return [Symbol]
attr_reader :operation_name
# Makes an API call, returning the resultant state and the response.
#
# * `:success` - A success state has been matched.
# * `:failure` - A terminate failure state has been matched.
# * `:retry` - The waiter may be retried.
# * `:error` - The waiter encountered an un-expected error.
#
# @example A trival (bad) example of a waiter that polls indefinetly.
#
# loop do
#
# state, resp = poller.call(client:client, params:{})
#
# case state
# when :success then return true
# when :failure then return false
# when :retry then next
# when :error then raise 'oops'
# end
#
# end
#
# @option options [required,Client] :client
# @option options [required,Hash] :params
# @return [Array<Symbol,Response>]
def call(options = {})
response = send_request(options)
@acceptors.each do |acceptor|
if acceptor_matches?(acceptor, response)
return [acceptor['state'].to_sym, response]
end
end
[response.error ? :error : :retry, response]
end
private
def send_request(options)
req = options[:client].build_request(@operation_name, options[:params])
req.handlers.remove(RAISE_HANDLER)
req.send_request
end
def acceptor_matches?(acceptor, response)
send("matches_#{acceptor['matcher']}?", acceptor, response)
end
def matches_path?(acceptor, response)
if response.data
JMESPath.search(path(acceptor), response.data) == acceptor['expected']
else
false
end
end
def matches_pathAll?(acceptor, response)
non_empty_array(acceptor, response) do |values|
values.all? { |value| value == acceptor['expected'] }
end
end
def matches_pathAny?(acceptor, response)
non_empty_array(acceptor, response) do |values|
values.any? { |value| value == acceptor['expected'] }
end
end
def matches_status?(acceptor, response)
response.context.http_response.status_code == acceptor['expected']
end
def matches_error?(acceptor, response)
Aws::Errors::ServiceError === response.error &&
response.error.code == acceptor['expected'].gsub('.', '')
end
def path(acceptor)
acceptor['argument']
end
def non_empty_array(acceptor, response, &block)
if response.data
values = JMESPath.search(path(acceptor), response.data)
Array === values && values.count > 0 ? yield(values) : false
else
false
end
end
end
end
end
|