Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ void DynamoDBClientConfiguration::LoadDynamoDBSpecificConfig(const Aws::String&
enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, inputProfileName);
}
this->configFactories.retryStrategyCreateFn = []() -> std::shared_ptr<Client::RetryStrategy> {
// TODO: renable once default retries are evaluated
// Align with other SDKs to default retry to 10 times for dynamodb.
// return Client::InitRetryStrategy(10);
return Client::InitRetryStrategy();
return Client::InitRetryStrategy(4, "", 0.025);
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

#pragma once

#include <aws/core/client/GenericClientConfiguration.h>
#include <aws/dynamodbstreams/DynamoDBStreams_EXPORTS.h>

namespace Aws {
namespace DynamoDBStreams {
struct AWS_DYNAMODBSTREAMS_API DynamoDBStreamsClientConfiguration : public Aws::Client::GenericClientConfiguration {
using BaseClientConfigClass = Aws::Client::GenericClientConfiguration;

DynamoDBStreamsClientConfiguration(const Aws::Client::ClientConfigurationInitValues& configuration = {});

/**
* Create a configuration based on settings in the aws configuration file for the given profile name.
* The configuration file location can be set via the environment variable AWS_CONFIG_FILE
* @param profileName the aws profile name.
* @param shouldDisableIMDS whether or not to disable IMDS calls.
*/
DynamoDBStreamsClientConfiguration(const char* profileName, bool shouldDisableIMDS = false);

/**
* Create a configuration with a predefined smart defaults
* @param useSmartDefaults, required to differentiate c-tors
* @param defaultMode, default mode to use
* @param shouldDisableIMDS whether or not to disable IMDS calls.
*/
DynamoDBStreamsClientConfiguration(bool useSmartDefaults, const char* defaultMode = "legacy", bool shouldDisableIMDS = false);

/**
* Converting constructors for compatibility with a legacy code
*/
DynamoDBStreamsClientConfiguration(const Aws::Client::ClientConfiguration& config);

private:
void LoadDynamoDBStreamsSpecificConfig(const Aws::String& profileName);
};
} // namespace DynamoDBStreams
} // namespace Aws
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,30 @@
*/

#pragma once
#include <aws/core/client/GenericClientConfiguration.h>
#include <aws/core/endpoint/DefaultEndpointProvider.h>
#include <aws/core/endpoint/EndpointParameter.h>
#include <aws/core/utils/memory/stl/AWSString.h>
#include <aws/core/utils/memory/stl/AWSVector.h>
#include <aws/dynamodbstreams/DynamoDBStreamsClientConfiguration.h>
#include <aws/dynamodbstreams/DynamoDBStreamsEndpointRules.h>
#include <aws/dynamodbstreams/DynamoDBStreams_EXPORTS.h>

namespace Aws {
namespace DynamoDBStreams {
namespace Endpoint {
using DynamoDBStreamsClientConfiguration = Aws::DynamoDBStreams::DynamoDBStreamsClientConfiguration;
using EndpointParameters = Aws::Endpoint::EndpointParameters;
using Aws::Endpoint::DefaultEndpointProvider;
using Aws::Endpoint::EndpointProviderBase;

using DynamoDBStreamsClientContextParameters = Aws::Endpoint::ClientContextParameters;

using DynamoDBStreamsClientConfiguration = Aws::Client::GenericClientConfiguration;
using DynamoDBStreamsBuiltInParameters = Aws::Endpoint::BuiltInParameters;
class AWS_DYNAMODBSTREAMS_API DynamoDBStreamsBuiltInParameters : public Aws::Endpoint::BuiltInParameters {
public:
virtual ~DynamoDBStreamsBuiltInParameters() {};
using Aws::Endpoint::BuiltInParameters::SetFromClientConfiguration;
virtual void SetFromClientConfiguration(const DynamoDBStreamsClientConfiguration& config);
};

/**
* The type for the DynamoDBStreams Client Endpoint Provider.
Expand All @@ -35,6 +40,24 @@ using DynamoDBStreamsEndpointProviderBase =
using DynamoDBStreamsDefaultEpProviderBase =
DefaultEndpointProvider<DynamoDBStreamsClientConfiguration, DynamoDBStreamsBuiltInParameters, DynamoDBStreamsClientContextParameters>;

} // namespace Endpoint
} // namespace DynamoDBStreams

namespace Endpoint {
/**
* Export endpoint provider symbols for Windows DLL, otherwise declare as extern
*/
AWS_DYNAMODBSTREAMS_EXTERN template class AWS_DYNAMODBSTREAMS_API Aws::Endpoint::EndpointProviderBase<
DynamoDBStreams::Endpoint::DynamoDBStreamsClientConfiguration, DynamoDBStreams::Endpoint::DynamoDBStreamsBuiltInParameters,
DynamoDBStreams::Endpoint::DynamoDBStreamsClientContextParameters>;

AWS_DYNAMODBSTREAMS_EXTERN template class AWS_DYNAMODBSTREAMS_API Aws::Endpoint::DefaultEndpointProvider<
DynamoDBStreams::Endpoint::DynamoDBStreamsClientConfiguration, DynamoDBStreams::Endpoint::DynamoDBStreamsBuiltInParameters,
DynamoDBStreams::Endpoint::DynamoDBStreamsClientContextParameters>;
} // namespace Endpoint

namespace DynamoDBStreams {
namespace Endpoint {
/**
* Default endpoint provider used for this service
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class RetryStrategy;
} // namespace Client

namespace DynamoDBStreams {
using DynamoDBStreamsClientConfiguration = Aws::Client::GenericClientConfiguration;
using DynamoDBStreamsEndpointProviderBase = Aws::DynamoDBStreams::Endpoint::DynamoDBStreamsEndpointProviderBase;
using DynamoDBStreamsEndpointProvider = Aws::DynamoDBStreams::Endpoint::DynamoDBStreamsEndpointProvider;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

#include <aws/dynamodbstreams/DynamoDBStreamsClientConfiguration.h>

namespace Aws {
namespace DynamoDBStreams {

void DynamoDBStreamsClientConfiguration::LoadDynamoDBStreamsSpecificConfig(const Aws::String& inputProfileName) {
this->configFactories.retryStrategyCreateFn = []() -> std::shared_ptr<Client::RetryStrategy> {
return Client::InitRetryStrategy(4, "", 0.025);
};
#if defined(_MSC_VER)
(&reinterpret_cast<const int&>(inputProfileName));
#else
(void)(inputProfileName);
#endif
}

DynamoDBStreamsClientConfiguration::DynamoDBStreamsClientConfiguration(const Aws::Client::ClientConfigurationInitValues& configuration)
: BaseClientConfigClass(configuration) {
LoadDynamoDBStreamsSpecificConfig(this->profileName);
}

DynamoDBStreamsClientConfiguration::DynamoDBStreamsClientConfiguration(const char* inputProfileName, bool shouldDisableIMDS)
: BaseClientConfigClass(inputProfileName, shouldDisableIMDS) {
LoadDynamoDBStreamsSpecificConfig(Aws::String(inputProfileName));
}

DynamoDBStreamsClientConfiguration::DynamoDBStreamsClientConfiguration(bool useSmartDefaults, const char* defaultMode,
bool shouldDisableIMDS)
: BaseClientConfigClass(useSmartDefaults, defaultMode, shouldDisableIMDS) {
LoadDynamoDBStreamsSpecificConfig(this->profileName);
}

DynamoDBStreamsClientConfiguration::DynamoDBStreamsClientConfiguration(const Aws::Client::ClientConfiguration& config)
: BaseClientConfigClass(config) {
LoadDynamoDBStreamsSpecificConfig(this->profileName);
}

} // namespace DynamoDBStreams
} // namespace Aws
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,27 @@
#include <aws/dynamodbstreams/DynamoDBStreamsEndpointProvider.h>

namespace Aws {
#ifndef AWS_DYNAMODBSTREAMS_EXPORTS // Except for Windows DLL
namespace Endpoint {
/**
* Instantiate endpoint providers
*/
template class Aws::Endpoint::EndpointProviderBase<DynamoDBStreams::Endpoint::DynamoDBStreamsClientConfiguration,
DynamoDBStreams::Endpoint::DynamoDBStreamsBuiltInParameters,
DynamoDBStreams::Endpoint::DynamoDBStreamsClientContextParameters>;

template class Aws::Endpoint::DefaultEndpointProvider<DynamoDBStreams::Endpoint::DynamoDBStreamsClientConfiguration,
DynamoDBStreams::Endpoint::DynamoDBStreamsBuiltInParameters,
DynamoDBStreams::Endpoint::DynamoDBStreamsClientContextParameters>;
} // namespace Endpoint
#endif

namespace DynamoDBStreams {
namespace Endpoint {} // namespace Endpoint
namespace Endpoint {
void DynamoDBStreamsBuiltInParameters::SetFromClientConfiguration(const DynamoDBStreamsClientConfiguration& config) {
SetFromClientConfiguration(static_cast<const DynamoDBStreamsClientConfiguration::BaseClientConfigClass&>(config));
}

} // namespace Endpoint
} // namespace DynamoDBStreams
} // namespace Aws
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ReceiveMessageRequest : public SQSRequest {
// so we can not get operation's name from response.
inline virtual const char* GetServiceRequestName() const override { return "ReceiveMessage"; }

inline virtual bool IsLongPollingOperation() const override { return true; }
AWS_SQS_API Aws::String SerializePayload() const override;

AWS_SQS_API Aws::Http::HeaderValueCollection GetRequestSpecificHeaders() const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class GetActivityTaskRequest : public SFNRequest {
// so we can not get operation's name from response.
inline virtual const char* GetServiceRequestName() const override { return "GetActivityTask"; }

inline virtual bool IsLongPollingOperation() const override { return true; }
AWS_SFN_API Aws::String SerializePayload() const override;

AWS_SFN_API Aws::Http::HeaderValueCollection GetRequestSpecificHeaders() const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class PollForActivityTaskRequest : public SWFRequest {
// so we can not get operation's name from response.
inline virtual const char* GetServiceRequestName() const override { return "PollForActivityTask"; }

inline virtual bool IsLongPollingOperation() const override { return true; }
AWS_SWF_API Aws::String SerializePayload() const override;

AWS_SWF_API Aws::Http::HeaderValueCollection GetRequestSpecificHeaders() const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class PollForDecisionTaskRequest : public SWFRequest {
// so we can not get operation's name from response.
inline virtual const char* GetServiceRequestName() const override { return "PollForDecisionTask"; }

inline virtual bool IsLongPollingOperation() const override { return true; }
AWS_SWF_API Aws::String SerializePayload() const override;

AWS_SWF_API Aws::Http::HeaderValueCollection GetRequestSpecificHeaders() const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <aws/testing/AwsTestHelpers.h>

#include <aws/dynamodbstreams/DynamoDBStreamsClient.h>
#include <aws/dynamodbstreams/DynamoDBStreamsClientConfiguration.h>
#include <aws/dynamodbstreams/DynamoDBStreamsEndpointProvider.h>
#include <aws/dynamodbstreams/DynamoDBStreamsEndpointRules.h>
#include <aws/dynamodbstreams/DynamoDBStreamsErrorMarshaller.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ namespace Aws
*/
virtual bool IsChunked() const { return false; }

/**
* Whether this operation is a long-polling operation (e.g. SQS ReceiveMessage).
* Long-polling operations apply a backoff delay before returning when retry quota is exhausted.
*/
virtual bool IsLongPollingOperation() const { return false; }

/**
* Register closure for request signed event.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ namespace Aws
*/
AWS_CORE_API std::shared_ptr<RetryStrategy> InitRetryStrategy(Aws::String retryMode = "");
AWS_CORE_API std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxRetries, Aws::String retryMode = "");
AWS_CORE_API std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxRetries, Aws::String retryMode, double transientBackoffBaseSec);

/**
* A helper function to compute a user agent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ namespace Aws
public:
StandardRetryStrategy(long maxAttempts = 3);
StandardRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts = 3);
StandardRetryStrategy(long maxAttempts, double transientBackoffBaseSec);
virtual ~StandardRetryStrategy();

virtual void RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome) override;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

#pragma once

#include <aws/core/Core_EXPORTS.h>
#include <aws/core/client/AWSError.h>
#include <aws/core/client/CoreErrors.h>
#include <aws/core/client/RetryStrategy.h>

namespace Aws {
namespace Client {
namespace Internal {

/**
* For long-polling operations (e.g. SQS ReceiveMessage), when the retry strategy
* returns ShouldRetry=false due to quota exhaustion (not max attempts), apply a
* backoff delay before returning the error to the caller. This prevents all blocked
* callers from slamming the service simultaneously after quota is restored.
*
* Returns the sleep duration in milliseconds, or 0 if no sleep is needed.
*/
inline long ComputeLongPollingSleepMs(
const AWSError<CoreErrors>& error,
long retries,
const std::shared_ptr<RetryStrategy>& retryStrategy,
bool isLongPollingOperation)
{
if (!isLongPollingOperation) return 0;
if (!error.ShouldRetry()) return 0;
if (retries + 1 >= retryStrategy->GetMaxAttempts()) return 0;

return retryStrategy->CalculateDelayBeforeNextRetry(error, retries);
}

} // namespace Internal
} // namespace Client
} // namespace Aws
7 changes: 7 additions & 0 deletions src/aws-cpp-sdk-core/source/client/AWSClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <aws/core/client/AWSClient.h>
#include <aws/core/AmazonWebServiceRequest.h>
#include <aws/core/internal/LongPollingRetryHelper.h>
#include <aws/core/auth/AWSAuthSigner.h>
#include <aws/core/auth/AWSAuthSignerProvider.h>
#include <aws/core/client/AWSUrlPresigner.h>
Expand Down Expand Up @@ -362,6 +363,12 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri,

if (!retryWithCorrectRegion && !m_retryStrategy->ShouldRetry(outcome.GetError(), retries))
{
long lpSleepMs = Internal::ComputeLongPollingSleepMs(
outcome.GetError(), retries, m_retryStrategy, request.IsLongPollingOperation());
if (lpSleepMs > 0)
{
m_httpClient->RetryRequestSleep(std::chrono::milliseconds(lpSleepMs));
}
break;
}
if (request.IsEventStreamRequest() &&
Expand Down
25 changes: 24 additions & 1 deletion src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ ClientConfiguration::ClientConfiguration(bool /*useSmartDefaults*/, const char*
Aws::Config::Defaults::SetSmartDefaultsConfigurationParameters(*this, defaultMode, hasEc2MetadataRegion, ec2MetadataRegion);
}

std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxAttempts, Aws::String retryMode) {
static Aws::String ResolveRetryMode(Aws::String retryMode) {
if (retryMode.empty())
{
retryMode = Aws::Environment::GetEnv("AWS_RETRY_MODE");
Expand All @@ -556,6 +556,11 @@ std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxAttempts, Aws::String re
{
retryMode = "standard";
}
return retryMode;
}

std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxAttempts, Aws::String retryMode) {
retryMode = ResolveRetryMode(retryMode);

std::shared_ptr<RetryStrategy> retryStrategy;
if (retryMode == "standard")
Expand Down Expand Up @@ -590,6 +595,24 @@ std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxAttempts, Aws::String re
return retryStrategy;
}

std::shared_ptr<RetryStrategy> InitRetryStrategy(int maxAttempts, Aws::String retryMode, double transientBackoffBaseSec) {
if (Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_NEW_RETRIES_2026").c_str()) != "true")
{
// Gate is off: ignore service-specific tuning, use default behavior
return InitRetryStrategy(-1, retryMode);
}

// Only standard mode honors a service-specific backoff base; other modes are unaffected,
// so they go through the default-base path.
if (ResolveRetryMode(retryMode) != "standard")
{
return InitRetryStrategy(maxAttempts, retryMode);
}

long attempts = (maxAttempts < 0) ? 3 : static_cast<long>(maxAttempts);
return Aws::MakeShared<StandardRetryStrategy>(CLIENT_CONFIG_TAG, attempts, transientBackoffBaseSec);
}

std::shared_ptr<RetryStrategy> InitRetryStrategy(Aws::String retryMode)
{
int maxAttempts = 0;
Expand Down
Loading
Loading