@@ -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