8#include <aws/core/utils/logging/LogMacros.h>
9#include <aws/crt/Variant.h>
27template <
typename OutcomeT>
36template <
typename OutcomeT>
39template <
typename RequestT,
typename OutcomeT>
41 bool Matches(
const Acceptor& acceptor,
const OutcomeT& outcome) {
44 int status = GetStatusCode(outcome);
45 return status == acceptor.
expected.get<
int>();
48 if (acceptor.
expected.holds_alternative<
bool>()) {
49 bool expectError = acceptor.
expected.get<
bool>();
50 return outcome.IsSuccess() != expectError;
52 if (!outcome.IsSuccess()) {
53 auto errorCode = outcome.GetError().GetExceptionName();
61 return m_pathMatcher(outcome, acceptor.
expected);
67 Waiter(
int delay,
int maxAttempts, std::vector<Acceptor> acceptors, std::function<OutcomeT(
const RequestT&)> op,
70 m_maxAttempts(maxAttempts),
71 m_acceptors(std::move(acceptors)),
72 m_operation(std::move(op)),
74 m_pathMatcher(std::move(pathMatcher)) {}
77 for (
int attempt = 0; attempt < m_maxAttempts; ++attempt) {
78 auto outcome = m_operation(request);
80 auto matched = std::find_if(m_acceptors.begin(), m_acceptors.end(),
81 [
this, &outcome](
const Acceptor& acceptor) ->
bool { return Matches(acceptor, outcome); });
82 if (matched != m_acceptors.end()) {
86 if (attempt < m_maxAttempts - 1) {
87 std::this_thread::sleep_for(std::chrono::seconds(m_delay));
90 AWS_LOG_TRACE(m_name.c_str(),
"Waiter hit max attempts");
97 std::vector<Acceptor> m_acceptors;
98 std::function<OutcomeT(
const RequestT&)> m_operation;
105 inline int GetStatusCode(OutcomeT outcome)
const {
106 return outcome.IsSuccess()
107 ? GetStatusCodeFromResult(outcome.GetResult())
108 : GetStatusCodeFromError(outcome.GetError());
112 struct has_get_http_response_code
115 static auto test(
int) ->
decltype(std::declval<U>().GetHttpResponseCode(), std::true_type());
118 static std::false_type test(...);
120 static constexpr bool value =
decltype(test<T>(0))::value;
124 struct has_get_response_code
127 static auto test(
int) ->
decltype(std::declval<U>().GetResponseCode(), std::true_type());
130 static std::false_type test(...);
132 static constexpr bool value =
decltype(test<T>(0))::value;
136 static int GetStatusCodeFromResult(
const T& result)
138 static_assert(has_get_http_response_code<T>::value,
"Result type must have GetHttpResponseCode() method");
139 return static_cast<int>(result.GetHttpResponseCode());
143 static int GetStatusCodeFromError(
const T& error)
145 static_assert(has_get_response_code<T>::value,
"Error type must have GetResponseCode() method");
146 return static_cast<int>(error.GetResponseCode());
WaiterOutcome< OutcomeT > Wait(const RequestT &request)
Waiter(int delay, int maxAttempts, std::vector< Acceptor > acceptors, std::function< OutcomeT(const RequestT &)> op, const Aws::String &waiterName="Waiter", PathMatcher< OutcomeT > pathMatcher=[](const OutcomeT &, const ExpectedValue &) { return false;})
Crt::Variant< int, bool, Aws::String > ExpectedValue
std::function< bool(const OutcomeT &, const ExpectedValue &)> PathMatcher
Aws::Client::AWSError< WaiterErrors > WaiterError
std::basic_string< char, std::char_traits< char >, Aws::Allocator< char > > String