1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 
6 #pragma once
7 
8 #include <aws/core/Core_EXPORTS.h>
9 #include <aws/core/utils/threading/ReaderWriterLock.h>
10 #include <memory>
11 
12 namespace Aws
13 {
14     namespace Http
15     {
16         class HttpResponse;
17     }
18 
19     namespace Utils
20     {
21         template<typename R, typename E>
22         class Outcome;
23     }
24 
25     namespace Client
26     {
27         enum class CoreErrors;
28         template<typename ERROR_TYPE>
29         class AWSError;
30 
31         typedef Utils::Outcome<std::shared_ptr<Aws::Http::HttpResponse>, AWSError<CoreErrors>> HttpResponseOutcome;
32 
33         /**
34          * Interface for defining a Retry Strategy. Override this class to provide your own custom retry behavior.
35          */
36         class AWS_CORE_API RetryStrategy
37         {
38         public:
39             virtual ~RetryStrategy() = default;
40             /**
41              * Returns true if the error can be retried given the error and the number of times already tried.
42              */
43             virtual bool ShouldRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const = 0;
44 
45             /**
46              * Calculates the time in milliseconds the client should sleep before attempting another request based on the error and attemptedRetries count.
47              */
48             virtual long CalculateDelayBeforeNextRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const = 0;
49 
50             /**
51              * Gets max number of attempts allowed for an operation.
52              * Returns non positive value if not defined.
53              */
GetMaxAttempts()54             virtual long GetMaxAttempts() const { return 0; }
55 
56             /**
57              * Retrives send tokens from the bucket.
58              */
GetSendToken()59             virtual void GetSendToken() {}
60 
61             /**
62              * Update status, like the information of retry quota when receiving a response.
63              */
RequestBookkeeping(const HttpResponseOutcome &)64             virtual void RequestBookkeeping(const HttpResponseOutcome& /* httpResponseOutcome */) {}
RequestBookkeeping(const HttpResponseOutcome &,const AWSError<CoreErrors> &)65             virtual void RequestBookkeeping(const HttpResponseOutcome& /* httpResponseOutcome */, const AWSError<CoreErrors>& /* lastError */) {}
66         };
67 
68         /**
69          * The container for retry quotas.
70          * A failed request will acquire retry quotas to retry.
71          * And a successful request will release quotas back.
72          * If running out of retry quotas, then the client is not able to retry.
73          */
74         class AWS_CORE_API RetryQuotaContainer
75         {
76         public:
77             virtual ~RetryQuotaContainer() = default;
78             virtual bool AcquireRetryQuota(int capacityAmount) = 0;
79             virtual bool AcquireRetryQuota(const AWSError<CoreErrors>& error) = 0;
80             virtual void ReleaseRetryQuota(int capacityAmount) = 0;
81             virtual void ReleaseRetryQuota(const AWSError<CoreErrors>& lastError) = 0;
82             virtual int GetRetryQuota() const = 0;
83         };
84 
85         class AWS_CORE_API DefaultRetryQuotaContainer : public RetryQuotaContainer
86         {
87         public:
88             DefaultRetryQuotaContainer();
89             virtual ~DefaultRetryQuotaContainer() = default;
90             virtual bool AcquireRetryQuota(int capacityAmount) override;
91             virtual bool AcquireRetryQuota(const AWSError<CoreErrors>& error) override;
92             virtual void ReleaseRetryQuota(int capacityAmount) override;
93             virtual void ReleaseRetryQuota(const AWSError<CoreErrors>& lastError) override;
GetRetryQuota()94             virtual int GetRetryQuota() const override { return m_retryQuota; }
95 
96         protected:
97             mutable Aws::Utils::Threading::ReaderWriterLock m_retryQuotaLock;
98             int m_retryQuota;
99         };
100 
101         class AWS_CORE_API StandardRetryStrategy : public RetryStrategy
102         {
103         public:
104             StandardRetryStrategy(long maxAttempts = 3);
105             StandardRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts = 3);
106 
107             virtual void RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome) override;
108             virtual void RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome, const AWSError<CoreErrors>& lastError) override;
109 
110             virtual bool ShouldRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const override;
111 
112             virtual long CalculateDelayBeforeNextRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const override;
113 
GetMaxAttempts()114             virtual long GetMaxAttempts() const override { return m_maxAttempts; }
115 
116         protected:
117             std::shared_ptr<RetryQuotaContainer> m_retryQuotaContainer;
118             long m_maxAttempts;
119         };
120     } // namespace Client
121 } // namespace Aws
122