diff --git a/generated/src/aws-cpp-sdk-s3/source/S3Errors.cpp b/generated/src/aws-cpp-sdk-s3/source/S3Errors.cpp index eb8a02f4723..951d6a35f60 100644 --- a/generated/src/aws-cpp-sdk-s3/source/S3Errors.cpp +++ b/generated/src/aws-cpp-sdk-s3/source/S3Errors.cpp @@ -42,6 +42,8 @@ static const int ANNOTATION_NAME_TOO_LONG_HASH = HashingUtils::HashString("Annot static const int OBJECT_NOT_IN_ACTIVE_TIER_HASH = HashingUtils::HashString("ObjectNotInActiveTierError"); static const int BUCKET_ALREADY_EXISTS_HASH = HashingUtils::HashString("BucketAlreadyExists"); static const int INVALID_OBJECT_STATE_HASH = HashingUtils::HashString("InvalidObjectState"); +// Wasabi returns this code for transient storage-service failures. +static const int TEMPORARILY_UNAVAILABLE_HASH = HashingUtils::HashString("TemporarilyUnavailable"); AWSError GetErrorForName(const char* errorName) { int hashCode = HashingUtils::HashString(errorName); @@ -85,6 +87,10 @@ AWSError GetErrorForName(const char* errorName) { } else if (hashCode == INVALID_OBJECT_STATE_HASH) { return AWSError(static_cast(S3Errors::INVALID_OBJECT_STATE), RetryableType::NOT_RETRYABLE); } + else if (hashCode == TEMPORARILY_UNAVAILABLE_HASH) + { + return AWSError(CoreErrors::SERVICE_UNAVAILABLE, RetryableType::RETRYABLE); + } return AWSError(CoreErrors::UNKNOWN, false); } diff --git a/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp index 69c3ab632c6..6e49d5bc86a 100644 --- a/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp +++ b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -363,6 +364,32 @@ class MockRequest : public Aws::AmazonWebServiceRequest }; //Set http error and error in body in a way to hit generic xml error marshaller, which sets the exception name +TEST_F(S3UnitTest, TemporarilyUnavailableIsRetryable) { + auto mockRequest = Aws::MakeShared( + ALLOCATION_TAG, "https://mock.example/bucket/key", HttpMethod::HTTP_PUT); + mockRequest->SetResponseStreamFactory([]() -> IOStream* { + return Aws::New(ALLOCATION_TAG); + }); + auto mockResponse = Aws::MakeShared(ALLOCATION_TAG, mockRequest); + mockResponse->GetResponseBody() + << "TemporarilyUnavailable" + "Storage service is temporarily not available."; + mockResponse->SetResponseCode(HttpResponseCode::SERVICE_UNAVAILABLE); + + const auto error = S3ErrorMarshaller().BuildAWSError(mockResponse); + EXPECT_EQ(CoreErrors::SERVICE_UNAVAILABLE, error.GetErrorType()); + EXPECT_EQ("TemporarilyUnavailable", error.GetExceptionName()); + EXPECT_TRUE(error.ShouldRetry()); + EXPECT_TRUE(DefaultRetryStrategy().ShouldRetry(error, 0)); +} + +TEST_F(S3UnitTest, UnknownS3ErrorRemainsNonRetryable) { + const auto error = S3ErrorMapper::GetErrorForName("UnknownStorageError"); + EXPECT_EQ(CoreErrors::UNKNOWN, error.GetErrorType()); + EXPECT_FALSE(error.ShouldRetry()); + EXPECT_FALSE(S3ErrorMapper::GetErrorForName("NoSuchKey").ShouldRetry()); +} + TEST_F(S3UnitTest, S3EmbeddedErrorTestNonOKResponse) { auto mockRequest = Aws::MakeShared(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET);