|
14 | 14 | #include <aws/core/utils/logging/LogMacros.h> |
15 | 15 |
|
16 | 16 | using namespace Aws::Utils::Threading; |
| 17 | +using namespace Aws::Client; |
17 | 18 |
|
18 | 19 | static const char RETRY_STRATEGY_TAG[] = "StandardRetryStrategy"; |
| 20 | +static const int INITIAL_RETRY_TOKENS = 500; |
| 21 | +static const int RETRY_COST = 5; |
| 22 | +static const int TIMEOUT_RETRY_COST = 10; |
19 | 23 |
|
20 | 24 | namespace Aws |
21 | 25 | { |
22 | 26 | namespace Client |
23 | 27 | { |
24 | | - static const int INITIAL_RETRY_TOKENS = 500; |
25 | | - static const int RETRY_COST = 5; |
26 | | - static const int TIMEOUT_RETRY_COST = 10; |
27 | | - |
28 | | - static bool IsNewRetriesEnabled() |
29 | | - { |
30 | | - return Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_NEW_RETRIES_2026").c_str()) == "true"; |
31 | | - } |
32 | | - |
33 | | - struct StandardRetryStrategy::RetryImpl |
| 28 | + class StandardRetryStrategy::RetryImpl |
34 | 29 | { |
| 30 | + public: |
35 | 31 | virtual ~RetryImpl() = default; |
36 | 32 | virtual long CalculateDelay(const AWSError<CoreErrors>& error, long attemptedRetries) const = 0; |
37 | 33 | }; |
| 34 | + } |
| 35 | +} |
| 36 | + |
| 37 | +namespace { |
| 38 | + bool IsNewRetriesEnabled() |
| 39 | + { |
| 40 | + return Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_NEW_RETRIES_2026").c_str()) == "true"; |
| 41 | + } |
38 | 42 |
|
39 | | - namespace { |
40 | | - struct LegacyRetryImpl : StandardRetryStrategy::RetryImpl |
| 43 | + class LegacyRetryImpl : public StandardRetryStrategy::RetryImpl |
| 44 | + { |
| 45 | + public: |
| 46 | + long CalculateDelay(const AWSError<CoreErrors>& error, long attemptedRetries) const override |
41 | 47 | { |
42 | | - long CalculateDelay(const AWSError<CoreErrors>& error, long attemptedRetries) const override |
43 | | - { |
44 | | - AWS_UNREFERENCED_PARAM(error); |
45 | | - // Maximum left shift factor is capped by ceil(log2(max_delay)), to avoid wrap-around and overflow into negative values: |
46 | | - return std::min(static_cast<int>(Aws::Utils::GetRandomValue() % 1000) * (1 << std::min(attemptedRetries, 15L)), 20000); |
47 | | - } |
48 | | - }; |
| 48 | + AWS_UNREFERENCED_PARAM(error); |
| 49 | + // Maximum left shift factor is capped by ceil(log2(max_delay)), to avoid wrap-around and overflow into negative values: |
| 50 | + return std::min(static_cast<int>(Aws::Utils::GetRandomValue() % 1000) * (1 << std::min(attemptedRetries, 15L)), 20000); |
| 51 | + } |
| 52 | + }; |
49 | 53 |
|
50 | | - struct NewRetriesImpl : StandardRetryStrategy::RetryImpl |
| 54 | + class NewRetriesImpl : public StandardRetryStrategy::RetryImpl |
| 55 | + { |
| 56 | + public: |
| 57 | + long CalculateDelay(const AWSError<CoreErrors>& error, long attemptedRetries) const override |
51 | 58 | { |
52 | | - long CalculateDelay(const AWSError<CoreErrors>& error, long attemptedRetries) const override |
53 | | - { |
54 | | - double x = error.ShouldThrottle() ? 1.0 : 0.05; |
55 | | - double exponentialPart = x * static_cast<double>(1L << (std::min)(attemptedRetries, 30L)); |
56 | | - double cappedPart = (std::min)(exponentialPart, 20.0); |
| 59 | + double x = error.ShouldThrottle() ? 1.0 : 0.05; |
| 60 | + double exponentialPart = x * static_cast<double>(1L << (std::min)(attemptedRetries, 30L)); |
| 61 | + double cappedPart = (std::min)(exponentialPart, 20.0); |
57 | 62 |
|
58 | | - double b = static_cast<double>(Aws::Utils::GetRandomValue() % 10000) / 10000.0; |
59 | | - double t_i = b * cappedPart; |
| 63 | + double b = static_cast<double>(Aws::Utils::GetRandomValue() % 10000) / 10000.0; |
| 64 | + double t_i = b * cappedPart; |
60 | 65 |
|
61 | | - const auto& headers = error.GetResponseHeaders(); |
62 | | - auto it = headers.find("x-amz-retry-after"); |
63 | | - if (it != headers.end()) |
| 66 | + const auto& headers = error.GetResponseHeaders(); |
| 67 | + auto it = headers.find("x-amz-retry-after"); |
| 68 | + if (it != headers.end()) |
| 69 | + { |
| 70 | + long long headerMs = Aws::Utils::StringUtils::ConvertToInt64(it->second.c_str()); |
| 71 | + if (headerMs < 0) |
64 | 72 | { |
65 | | - long long headerMs = Aws::Utils::StringUtils::ConvertToInt64(it->second.c_str()); |
66 | | - if (headerMs < 0) |
67 | | - { |
68 | | - AWS_LOGSTREAM_DEBUG(RETRY_STRATEGY_TAG, "Ignoring invalid x-amz-retry-after value: " << it->second); |
69 | | - } |
70 | | - double headerSec = static_cast<double>(headerMs) / 1000.0; |
71 | | - double clamped = (std::max)(t_i, (std::min)(headerSec, 5.0 + t_i)); |
72 | | - return static_cast<long>(clamped * 1000.0); |
| 73 | + AWS_LOGSTREAM_DEBUG(RETRY_STRATEGY_TAG, "Ignoring invalid x-amz-retry-after value: " << it->second); |
73 | 74 | } |
74 | | - |
75 | | - return static_cast<long>(t_i * 1000.0); |
| 75 | + double headerSec = static_cast<double>(headerMs) / 1000.0; |
| 76 | + double clamped = (std::max)(t_i, (std::min)(headerSec, 5.0 + t_i)); |
| 77 | + return static_cast<long>(clamped * 1000.0); |
76 | 78 | } |
77 | | - }; |
78 | | - } // anonymous namespace |
79 | 79 |
|
80 | | - static Aws::UniquePtr<StandardRetryStrategy::RetryImpl> CreateRetryImpl() |
| 80 | + return static_cast<long>(t_i * 1000.0); |
| 81 | + } |
| 82 | + }; |
| 83 | + |
| 84 | + Aws::UniquePtr<StandardRetryStrategy::RetryImpl> CreateRetryImpl() |
| 85 | + { |
| 86 | + if (IsNewRetriesEnabled()) |
81 | 87 | { |
82 | | - if (IsNewRetriesEnabled()) |
83 | | - { |
84 | | - return Aws::MakeUnique<NewRetriesImpl>("StandardRetryStrategy"); |
85 | | - } |
86 | | - return Aws::MakeUnique<LegacyRetryImpl>("StandardRetryStrategy"); |
| 88 | + return Aws::MakeUnique<NewRetriesImpl>("StandardRetryStrategy"); |
87 | 89 | } |
| 90 | + return Aws::MakeUnique<LegacyRetryImpl>("StandardRetryStrategy"); |
| 91 | + } |
88 | 92 |
|
89 | | - static std::shared_ptr<RetryQuotaContainer> CreateQuotaContainer() |
| 93 | + std::shared_ptr<RetryQuotaContainer> CreateQuotaContainer() |
| 94 | + { |
| 95 | + if (IsNewRetriesEnabled()) |
90 | 96 | { |
91 | | - if (IsNewRetriesEnabled()) |
92 | | - { |
93 | | - return Aws::MakeShared<ThrottleBasedRetryQuotaContainer>("StandardRetryStrategy"); |
94 | | - } |
95 | | - return Aws::MakeShared<DefaultRetryQuotaContainer>("StandardRetryStrategy"); |
| 97 | + return Aws::MakeShared<ThrottleBasedRetryQuotaContainer>("StandardRetryStrategy"); |
96 | 98 | } |
| 99 | + return Aws::MakeShared<DefaultRetryQuotaContainer>("StandardRetryStrategy"); |
| 100 | + } |
| 101 | +} // anonymous namespace |
97 | 102 |
|
| 103 | +namespace Aws |
| 104 | +{ |
| 105 | + namespace Client |
| 106 | + { |
98 | 107 | StandardRetryStrategy::StandardRetryStrategy(long maxAttempts) |
99 | 108 | : m_retryQuotaContainer(CreateQuotaContainer()), m_maxAttempts(maxAttempts), |
100 | 109 | m_impl(CreateRetryImpl()) {} |
|
0 commit comments