Skip to content

Commit a678b9b

Browse files
authored
Copy request for each attempt / don't retry client errors (#460)
1 parent f601fcf commit a678b9b

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

codegen/core/src/main/java/software/amazon/smithy/python/codegen/ClientGenerator.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ private void generateOperationExecutor(PythonWriter writer) {
132132
writer.addStdlibImport("typing", "Awaitable");
133133
writer.addStdlibImport("typing", "cast");
134134
writer.addStdlibImport("copy", "deepcopy");
135+
writer.addStdlibImport("copy", "copy");
135136
writer.addStdlibImport("asyncio");
136137
writer.addStdlibImports("asyncio", Set.of("sleep", "Future"));
137138
writer.addStdlibImport("dataclasses", "replace");
@@ -395,7 +396,10 @@ def _classify_error(
395396
output_context = await self._handle_attempt(
396397
deserialize,
397398
interceptor_chain,
398-
request_context,
399+
replace(
400+
request_context,
401+
transport_request = copy(request_context.transport_request)
402+
),
399403
config,
400404
operation,
401405
request_future,

packages/smithy-core/src/smithy_core/retries.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from dataclasses import dataclass
66
from enum import Enum
77

8+
from smithy_core.interfaces.retries import RetryErrorType
9+
810
from .exceptions import SmithyRetryException
911
from .interfaces import retries as retries_interface
1012

@@ -232,13 +234,16 @@ def refresh_retry_token_for_retry(
232234
233235
:raises SmithyRetryException: If no further retry attempts are allowed.
234236
"""
235-
retry_count = token_to_renew.retry_count + 1
236-
if retry_count >= self.max_attempts:
237-
raise SmithyRetryException(
238-
f"Reached maximum number of allowed attempts: {self.max_attempts}"
239-
)
240-
retry_delay = self.backoff_strategy.compute_next_backoff_delay(retry_count)
241-
return SimpleRetryToken(retry_count=retry_count, retry_delay=retry_delay)
237+
if error_info.error_type is not RetryErrorType.CLIENT_ERROR:
238+
retry_count = token_to_renew.retry_count + 1
239+
if retry_count >= self.max_attempts:
240+
raise SmithyRetryException(
241+
f"Reached maximum number of allowed attempts: {self.max_attempts}"
242+
)
243+
retry_delay = self.backoff_strategy.compute_next_backoff_delay(retry_count)
244+
return SimpleRetryToken(retry_count=retry_count, retry_delay=retry_delay)
245+
else:
246+
raise SmithyRetryException(f"Error is not retryable: {error_info}")
242247

243248
def record_success(self, *, token: retries_interface.RetryToken) -> None:
244249
"""Not used by this retry strategy."""

packages/smithy-core/tests/unit/test_retries.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,16 @@ def test_simple_retry_strategy(max_attempts: int) -> None:
7171
strategy.refresh_retry_token_for_retry(
7272
token_to_renew=token, error_info=error_info
7373
)
74+
75+
76+
def test_simple_retry_strategy_does_not_retry_client_errors() -> None:
77+
strategy = SimpleRetryStrategy(
78+
backoff_strategy=ExponentialRetryBackoffStrategy(backoff_scale_value=5),
79+
max_attempts=2,
80+
)
81+
error_info = RetryErrorInfo(error_type=RetryErrorType.CLIENT_ERROR)
82+
token = strategy.acquire_initial_retry_token()
83+
with pytest.raises(SmithyRetryException):
84+
strategy.refresh_retry_token_for_retry(
85+
token_to_renew=token, error_info=error_info
86+
)

0 commit comments

Comments
 (0)