AWS SDK for C++

AWS SDK for C++ Version 1.11.758

Loading...
Searching...
No Matches
Waiter.h
1
6#pragma once
7
8#include <aws/core/utils/logging/LogMacros.h>
9#include <aws/crt/Variant.h>
10
11#include <algorithm>
12#include <functional>
13#include <utility>
14#include <thread>
15#include <type_traits>
16
17namespace Aws {
18namespace Utils {
19
23
24using ExpectedValue = Crt::Variant<int, bool, Aws::String>;
26
27template <typename OutcomeT>
29
30struct Acceptor {
34};
35
36template <typename OutcomeT>
37using PathMatcher = std::function<bool(const OutcomeT&, const ExpectedValue&)>;
38
39template <typename RequestT, typename OutcomeT>
40class Waiter {
41 bool Matches(const Acceptor& acceptor, const OutcomeT& outcome) {
42 switch (acceptor.matcher) {
44 int status = GetStatusCode(outcome);
45 return status == acceptor.expected.get<int>();
46 }
47 case MatcherType::ERROR: {
48 if (acceptor.expected.holds_alternative<bool>()) {
49 bool expectError = acceptor.expected.get<bool>();
50 return outcome.IsSuccess() != expectError;
51 }
52 if (!outcome.IsSuccess()) {
53 auto errorCode = outcome.GetError().GetExceptionName();
54 return errorCode == acceptor.expected.get<Aws::String>();
55 }
56 return false;
57 }
61 return m_pathMatcher(outcome, acceptor.expected);
62 }
63 return false;
64 }
65
66 public:
67 Waiter(int delay, int maxAttempts, std::vector<Acceptor> acceptors, std::function<OutcomeT(const RequestT&)> op,
68 const Aws::String& waiterName = "Waiter", PathMatcher<OutcomeT> pathMatcher = [](const OutcomeT&, const ExpectedValue&) { return false; })
69 : m_delay(delay),
70 m_maxAttempts(maxAttempts),
71 m_acceptors(std::move(acceptors)),
72 m_operation(std::move(op)),
73 m_name(waiterName),
74 m_pathMatcher(std::move(pathMatcher)) {}
75
76 WaiterOutcome<OutcomeT> Wait(const RequestT& request) {
77 for (int attempt = 0; attempt < m_maxAttempts; ++attempt) {
78 auto outcome = m_operation(request);
79
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()) {
83 return WaiterOutcome<OutcomeT>(outcome);
84 }
85
86 if (attempt < m_maxAttempts - 1) {
87 std::this_thread::sleep_for(std::chrono::seconds(m_delay));
88 }
89 }
90 AWS_LOG_TRACE(m_name.c_str(), "Waiter hit max attempts");
91 return WaiterOutcome<OutcomeT>(WaiterError(WaiterErrors::MAX_ATTEMPTS, "", "Max attempts for operation reached", false /*retryable*/));
92 }
93
94private:
95 int m_delay;
96 int m_maxAttempts;
97 std::vector<Acceptor> m_acceptors;
98 std::function<OutcomeT(const RequestT&)> m_operation;
99 Aws::String m_name;
100 PathMatcher<OutcomeT> m_pathMatcher;
105 inline int GetStatusCode(OutcomeT outcome) const {
106 return outcome.IsSuccess()
107 ? GetStatusCodeFromResult(outcome.GetResult())
108 : GetStatusCodeFromError(outcome.GetError());
109 }
110
111 template<typename T>
112 struct has_get_http_response_code
113 {
114 template<typename U>
115 static auto test(int) -> decltype(std::declval<U>().GetHttpResponseCode(), std::true_type());
116
117 template<typename>
118 static std::false_type test(...);
119
120 static constexpr bool value = decltype(test<T>(0))::value;
121 };
122
123 template<typename T>
124 struct has_get_response_code
125 {
126 template<typename U>
127 static auto test(int) -> decltype(std::declval<U>().GetResponseCode(), std::true_type());
128
129 template<typename>
130 static std::false_type test(...);
131
132 static constexpr bool value = decltype(test<T>(0))::value;
133 };
134
135 template<typename T>
136 static int GetStatusCodeFromResult(const T& result)
137 {
138 static_assert(has_get_http_response_code<T>::value, "Result type must have GetHttpResponseCode() method");
139 return static_cast<int>(result.GetHttpResponseCode());
140 }
141
142 template<typename T>
143 static int GetStatusCodeFromError(const T& error)
144 {
145 static_assert(has_get_response_code<T>::value, "Error type must have GetResponseCode() method");
146 return static_cast<int>(error.GetResponseCode());
147 }
148
149};
150} // namespace Utils
151} // namespace Aws
WaiterOutcome< OutcomeT > Wait(const RequestT &request)
Definition Waiter.h:76
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;})
Definition Waiter.h:67
Crt::Variant< int, bool, Aws::String > ExpectedValue
Definition Waiter.h:24
std::function< bool(const OutcomeT &, const ExpectedValue &)> PathMatcher
Definition Waiter.h:37
Aws::Client::AWSError< WaiterErrors > WaiterError
Definition Waiter.h:25
std::basic_string< char, std::char_traits< char >, Aws::Allocator< char > > String
Definition AWSString.h:97
WaiterState state
Definition Waiter.h:31
ExpectedValue expected
Definition Waiter.h:33
MatcherType matcher
Definition Waiter.h:32