Skip to content

Commit 965a186

Browse files
committed
removed transient back off
1 parent 8416718 commit 965a186

5 files changed

Lines changed: 91 additions & 104 deletions

File tree

src/aws-cpp-sdk-core/include/aws/core/client/AdaptiveRetryStrategy.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,6 @@ class AWS_CORE_API AdaptiveRetryStrategy : public StandardRetryStrategy
141141

142142
const char* GetStrategyName() const override { return "adaptive";}
143143

144-
AdaptiveRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts, double transientBackoffBaseSec);
145-
146144
protected:
147145
RetryTokenBucket m_retryTokenBucket;
148146
bool m_fastFail = false;

src/aws-cpp-sdk-core/include/aws/core/client/RetryStrategy.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,10 @@ namespace Aws
103103
virtual int GetRetryQuota() const = 0;
104104
};
105105

106-
enum class RetryCostClassification
107-
{
108-
REQUEST_TIMEOUT_BASED,
109-
THROTTLE_BASED
110-
};
111-
112106
class AWS_CORE_API DefaultRetryQuotaContainer : public RetryQuotaContainer
113107
{
114108
public:
115109
DefaultRetryQuotaContainer();
116-
DefaultRetryQuotaContainer(int retryCost, int throttlingRetryCost, RetryCostClassification classification);
117110
virtual ~DefaultRetryQuotaContainer() = default;
118111
virtual bool AcquireRetryQuota(int capacityAmount) override;
119112
virtual bool AcquireRetryQuota(const AWSError<CoreErrors>& error) override;
@@ -124,17 +117,13 @@ namespace Aws
124117
protected:
125118
mutable Aws::Utils::Threading::ReaderWriterLock m_retryQuotaLock;
126119
int m_retryQuota;
127-
int m_retryCost;
128-
int m_throttlingRetryCost;
129-
RetryCostClassification m_classification;
130120
};
131121

132122
class AWS_CORE_API StandardRetryStrategy : public RetryStrategy
133123
{
134124
public:
135125
StandardRetryStrategy(long maxAttempts = 3);
136126
StandardRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts = 3);
137-
StandardRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts, double transientBackoffBaseSec);
138127
virtual ~StandardRetryStrategy();
139128

140129
virtual void RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome) override;

src/aws-cpp-sdk-core/source/client/AdaptiveRetryStrategy.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,6 @@ namespace Aws
169169
StandardRetryStrategy(retryQuotaContainer, maxAttempts)
170170
{}
171171

172-
AdaptiveRetryStrategy::AdaptiveRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts, double transientBackoffBaseSec) :
173-
StandardRetryStrategy(retryQuotaContainer, maxAttempts, transientBackoffBaseSec)
174-
{}
175-
176172
bool AdaptiveRetryStrategy::HasSendToken()
177173
{
178174
return m_retryTokenBucket.Acquire(1, m_fastFail);

src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,49 @@ ClientConfiguration::ClientConfiguration(bool /*useSmartDefaults*/, const char*
543543
Aws::Config::Defaults::SetSmartDefaultsConfigurationParameters(*this, defaultMode, hasEc2MetadataRegion, ec2MetadataRegion);
544544
}
545545

546+
namespace {
547+
class ThrottleBasedRetryQuotaContainer : public RetryQuotaContainer
548+
{
549+
public:
550+
ThrottleBasedRetryQuotaContainer(int retryCost = 14, int throttlingRetryCost = 5)
551+
: m_retryQuota(500), m_retryCost(retryCost), m_throttlingRetryCost(throttlingRetryCost) {}
552+
553+
bool AcquireRetryQuota(int capacityAmount) override
554+
{
555+
Aws::Utils::Threading::WriterLockGuard guard(m_retryQuotaLock);
556+
if (capacityAmount > m_retryQuota) return false;
557+
m_retryQuota -= capacityAmount;
558+
return true;
559+
}
560+
561+
bool AcquireRetryQuota(const AWSError<CoreErrors>& error) override
562+
{
563+
int capacityAmount = error.ShouldThrottle() ? m_throttlingRetryCost : m_retryCost;
564+
return AcquireRetryQuota(capacityAmount);
565+
}
566+
567+
void ReleaseRetryQuota(int capacityAmount) override
568+
{
569+
Aws::Utils::Threading::WriterLockGuard guard(m_retryQuotaLock);
570+
m_retryQuota = (std::min)(m_retryQuota + capacityAmount, 500);
571+
}
572+
573+
void ReleaseRetryQuota(const AWSError<CoreErrors>& error) override
574+
{
575+
int capacityAmount = error.ShouldThrottle() ? m_throttlingRetryCost : m_retryCost;
576+
ReleaseRetryQuota(capacityAmount);
577+
}
578+
579+
int GetRetryQuota() const override { return m_retryQuota; }
580+
581+
private:
582+
mutable Aws::Utils::Threading::ReaderWriterLock m_retryQuotaLock;
583+
int m_retryQuota;
584+
int m_retryCost;
585+
int m_throttlingRetryCost;
586+
};
587+
} // anonymous namespace
588+
546589
std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxAttempts, Aws::String retryMode) {
547590
const bool newRetriesEnabled = Aws::Environment::GetEnv("AWS_NEW_RETRIES_2026") == "true";
548591

@@ -565,8 +608,8 @@ std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxAttempts, Aws::String re
565608
long attempts = (maxAttempts < 0) ? 3 : maxAttempts;
566609
if (newRetriesEnabled)
567610
{
568-
auto quota = Aws::MakeShared<DefaultRetryQuotaContainer>(CLIENT_CONFIG_TAG, 14, 5, RetryCostClassification::THROTTLE_BASED);
569-
retryStrategy = Aws::MakeShared<StandardRetryStrategy>(CLIENT_CONFIG_TAG, quota, attempts, 0.05);
611+
auto quota = Aws::MakeShared<ThrottleBasedRetryQuotaContainer>(CLIENT_CONFIG_TAG);
612+
retryStrategy = Aws::MakeShared<StandardRetryStrategy>(CLIENT_CONFIG_TAG, quota, attempts);
570613
}
571614
else
572615
{
@@ -578,8 +621,8 @@ std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxAttempts, Aws::String re
578621
long attempts = (maxAttempts < 0) ? 3 : maxAttempts;
579622
if (newRetriesEnabled)
580623
{
581-
auto quota = Aws::MakeShared<DefaultRetryQuotaContainer>(CLIENT_CONFIG_TAG, 14, 5, RetryCostClassification::THROTTLE_BASED);
582-
retryStrategy = Aws::MakeShared<AdaptiveRetryStrategy>(CLIENT_CONFIG_TAG, quota, attempts, 0.05);
624+
auto quota = Aws::MakeShared<ThrottleBasedRetryQuotaContainer>(CLIENT_CONFIG_TAG);
625+
retryStrategy = Aws::MakeShared<AdaptiveRetryStrategy>(CLIENT_CONFIG_TAG, quota, attempts);
583626
}
584627
else
585628
{

src/aws-cpp-sdk-core/source/client/RetryStrategy.cpp

Lines changed: 44 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -20,95 +20,20 @@ namespace Aws
2020
static const int RETRY_COST = 5;
2121
static const int TIMEOUT_RETRY_COST = 10;
2222

23-
// ---- DefaultRetryQuotaContainer ----
24-
25-
DefaultRetryQuotaContainer::DefaultRetryQuotaContainer()
26-
: m_retryQuota(INITIAL_RETRY_TOKENS),
27-
m_retryCost(RETRY_COST),
28-
m_throttlingRetryCost(TIMEOUT_RETRY_COST),
29-
m_classification(RetryCostClassification::REQUEST_TIMEOUT_BASED)
30-
{}
31-
32-
DefaultRetryQuotaContainer::DefaultRetryQuotaContainer(int retryCost, int throttlingRetryCost, RetryCostClassification classification)
33-
: m_retryQuota(INITIAL_RETRY_TOKENS),
34-
m_retryCost(retryCost),
35-
m_throttlingRetryCost(throttlingRetryCost),
36-
m_classification(classification)
37-
{}
38-
39-
bool DefaultRetryQuotaContainer::AcquireRetryQuota(int capacityAmount)
40-
{
41-
WriterLockGuard guard(m_retryQuotaLock);
42-
43-
if (capacityAmount > m_retryQuota)
44-
{
45-
return false;
46-
}
47-
m_retryQuota -= capacityAmount;
48-
return true;
49-
}
50-
51-
bool DefaultRetryQuotaContainer::AcquireRetryQuota(const AWSError<CoreErrors>& error)
52-
{
53-
int capacityAmount;
54-
if (m_classification == RetryCostClassification::THROTTLE_BASED)
55-
{
56-
capacityAmount = error.ShouldThrottle() ? m_throttlingRetryCost : m_retryCost;
57-
}
58-
else
59-
{
60-
capacityAmount = error.GetErrorType() == CoreErrors::REQUEST_TIMEOUT ? TIMEOUT_RETRY_COST : RETRY_COST;
61-
}
62-
return AcquireRetryQuota(capacityAmount);
63-
}
64-
65-
void DefaultRetryQuotaContainer::ReleaseRetryQuota(int capacityAmount)
66-
{
67-
WriterLockGuard guard(m_retryQuotaLock);
68-
m_retryQuota = (std::min)(m_retryQuota + capacityAmount, INITIAL_RETRY_TOKENS);
69-
}
70-
71-
void DefaultRetryQuotaContainer::ReleaseRetryQuota(const AWSError<CoreErrors>& error)
72-
{
73-
int capacityAmount;
74-
if (m_classification == RetryCostClassification::THROTTLE_BASED)
75-
{
76-
capacityAmount = error.ShouldThrottle() ? m_throttlingRetryCost : m_retryCost;
77-
}
78-
else
79-
{
80-
capacityAmount = error.GetErrorType() == CoreErrors::REQUEST_TIMEOUT ? TIMEOUT_RETRY_COST : RETRY_COST;
81-
}
82-
ReleaseRetryQuota(capacityAmount);
83-
}
84-
85-
// ---- StandardRetryStrategy pimpl ----
86-
8723
struct StandardRetryStrategy::RetryImpl
8824
{
8925
bool newRetriesEnabled = false;
90-
double transientBackoffBaseSec = 0.05;
9126
};
9227

9328
StandardRetryStrategy::StandardRetryStrategy(long maxAttempts)
94-
: m_retryQuotaContainer(Aws::MakeShared<DefaultRetryQuotaContainer>("StandardRetryStrategy")),
95-
m_maxAttempts(maxAttempts),
96-
m_impl(Aws::MakeUnique<RetryImpl>("StandardRetryStrategy"))
97-
{}
29+
: m_retryQuotaContainer(Aws::MakeShared<DefaultRetryQuotaContainer>("StandardRetryStrategy")), m_maxAttempts(maxAttempts),
30+
m_impl(Aws::MakeUnique<RetryImpl>("StandardRetryStrategy")) {}
9831

9932
StandardRetryStrategy::StandardRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts)
100-
: m_retryQuotaContainer(retryQuotaContainer),
101-
m_maxAttempts(maxAttempts),
102-
m_impl(Aws::MakeUnique<RetryImpl>("StandardRetryStrategy"))
103-
{}
104-
105-
StandardRetryStrategy::StandardRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts, double transientBackoffBaseSec)
106-
: m_retryQuotaContainer(retryQuotaContainer),
107-
m_maxAttempts(maxAttempts),
33+
: m_retryQuotaContainer(retryQuotaContainer), m_maxAttempts(maxAttempts),
10834
m_impl(Aws::MakeUnique<RetryImpl>("StandardRetryStrategy"))
10935
{
11036
m_impl->newRetriesEnabled = true;
111-
m_impl->transientBackoffBaseSec = transientBackoffBaseSec;
11237
}
11338

11439
StandardRetryStrategy::~StandardRetryStrategy() = default;
@@ -145,12 +70,13 @@ namespace Aws
14570
if (!m_impl->newRetriesEnabled)
14671
{
14772
AWS_UNREFERENCED_PARAM(error);
148-
return (std::min)(static_cast<int>(Aws::Utils::GetRandomValue() % 1000) * (1 << (std::min)(attemptedRetries, 15L)), 20000);
73+
// Maximum left shift factor is capped by ceil(log2(max_delay)), to avoid wrap-around and overflow into negative values:
74+
return std::min(static_cast<int>(Aws::Utils::GetRandomValue() % 1000) * (1 << std::min(attemptedRetries, 15L)), 20000);
14975
}
15076

151-
double x = error.ShouldThrottle() ? 1.0 : m_impl->transientBackoffBaseSec;
152-
double exponentialPart = x * static_cast<double>(1L << (std::min)(attemptedRetries, 30L));
153-
double cappedPart = (std::min)(exponentialPart, 20.0);
77+
double x = error.ShouldThrottle() ? 1.0 : 0.05;
78+
double exponentialPart = x * static_cast<double>(1L << std::min(attemptedRetries, 30L));
79+
double cappedPart = std::min(exponentialPart, 20.0);
15480

15581
double b = static_cast<double>(Aws::Utils::GetRandomValue() % 10000) / 10000.0;
15682
double t_i = b * cappedPart;
@@ -160,12 +86,47 @@ namespace Aws
16086
if (it != headers.end())
16187
{
16288
double headerSec = static_cast<double>(Aws::Utils::StringUtils::ConvertToInt64(it->second.c_str())) / 1000.0;
163-
double clamped = (std::max)(t_i, (std::min)(headerSec, 5.0 + t_i));
89+
double clamped = std::max(t_i, std::min(headerSec, 5.0 + t_i));
16490
return static_cast<long>(clamped * 1000.0);
16591
}
16692

16793
return static_cast<long>(t_i * 1000.0);
16894
}
16995

96+
DefaultRetryQuotaContainer::DefaultRetryQuotaContainer() : m_retryQuota(INITIAL_RETRY_TOKENS)
97+
{}
98+
99+
bool DefaultRetryQuotaContainer::AcquireRetryQuota(int capacityAmount)
100+
{
101+
WriterLockGuard guard(m_retryQuotaLock);
102+
103+
if (capacityAmount > m_retryQuota)
104+
{
105+
return false;
106+
}
107+
else
108+
{
109+
m_retryQuota -= capacityAmount;
110+
return true;
111+
}
112+
}
113+
114+
bool DefaultRetryQuotaContainer::AcquireRetryQuota(const AWSError<CoreErrors>& error)
115+
{
116+
int capacityAmount = error.GetErrorType() == CoreErrors::REQUEST_TIMEOUT ? TIMEOUT_RETRY_COST : RETRY_COST;
117+
return AcquireRetryQuota(capacityAmount);
118+
}
119+
120+
void DefaultRetryQuotaContainer::ReleaseRetryQuota(int capacityAmount)
121+
{
122+
WriterLockGuard guard(m_retryQuotaLock);
123+
m_retryQuota = (std::min)(m_retryQuota + capacityAmount, INITIAL_RETRY_TOKENS);
124+
}
125+
126+
void DefaultRetryQuotaContainer::ReleaseRetryQuota(const AWSError<CoreErrors>& error)
127+
{
128+
int capacityAmount = error.GetErrorType() == CoreErrors::REQUEST_TIMEOUT ? TIMEOUT_RETRY_COST : RETRY_COST;
129+
ReleaseRetryQuota(capacityAmount);
130+
}
170131
}
171132
}

0 commit comments

Comments
 (0)