blob: 77b6f5abbbdf2327785b4559ce0dd4f53656ae2d (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/core/client/RetryStrategy.h>
#include <aws/core/client/AWSError.h>
#include <aws/core/client/CoreErrors.h>
#include <aws/core/utils/Outcome.h>
using namespace Aws::Utils::Threading;
namespace Aws
{
namespace Client
{
static const int INITIAL_RETRY_TOKENS = 500;
static const int RETRY_COST = 5;
static const int TIMEOUT_RETRY_COST = 10;
StandardRetryStrategy::StandardRetryStrategy(long maxAttempts) :
m_retryQuotaContainer(Aws::MakeShared<DefaultRetryQuotaContainer>("StandardRetryStrategy")),
m_maxAttempts(maxAttempts)
{
srand((unsigned int)time(NULL));
}
StandardRetryStrategy::StandardRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts) :
m_retryQuotaContainer(retryQuotaContainer),
m_maxAttempts(maxAttempts)
{
srand((unsigned int)time(NULL));
}
void StandardRetryStrategy::RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome)
{
if (httpResponseOutcome.IsSuccess())
{
m_retryQuotaContainer->ReleaseRetryQuota(NO_RETRY_INCREMENT);
}
}
void StandardRetryStrategy::RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome, const AWSError<CoreErrors>& lastError)
{
if (httpResponseOutcome.IsSuccess())
{
m_retryQuotaContainer->ReleaseRetryQuota(lastError);
}
}
bool StandardRetryStrategy::ShouldRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const
{
if (!error.ShouldRetry())
return false;
if (attemptedRetries + 1 >= m_maxAttempts)
return false;
return m_retryQuotaContainer->AcquireRetryQuota(error);
}
long StandardRetryStrategy::CalculateDelayBeforeNextRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const
{
AWS_UNREFERENCED_PARAM(error);
// Maximum left shift factor is capped by ceil(log2(max_delay)), to avoid wrap-around and overflow into negative values:
return (std::min)(rand() % 1000 * (1 << (std::min)(attemptedRetries, 15L)), 20000);
}
DefaultRetryQuotaContainer::DefaultRetryQuotaContainer() : m_retryQuota(INITIAL_RETRY_TOKENS)
{}
bool DefaultRetryQuotaContainer::AcquireRetryQuota(int capacityAmount)
{
WriterLockGuard guard(m_retryQuotaLock);
if (capacityAmount > m_retryQuota)
{
return false;
}
else
{
m_retryQuota -= capacityAmount;
return true;
}
}
bool DefaultRetryQuotaContainer::AcquireRetryQuota(const AWSError<CoreErrors>& error)
{
int capacityAmount = error.GetErrorType() == CoreErrors::REQUEST_TIMEOUT ? TIMEOUT_RETRY_COST : RETRY_COST;
return AcquireRetryQuota(capacityAmount);
}
void DefaultRetryQuotaContainer::ReleaseRetryQuota(int capacityAmount)
{
WriterLockGuard guard(m_retryQuotaLock);
m_retryQuota = (std::min)(m_retryQuota + capacityAmount, INITIAL_RETRY_TOKENS);
}
void DefaultRetryQuotaContainer::ReleaseRetryQuota(const AWSError<CoreErrors>& error)
{
int capacityAmount = error.GetErrorType() == CoreErrors::REQUEST_TIMEOUT ? TIMEOUT_RETRY_COST : RETRY_COST;
ReleaseRetryQuota(capacityAmount);
}
}
}
|