Skip to content

Conversation

@SamRemis
Copy link
Contributor

@SamRemis SamRemis commented Nov 7, 2025

Summary

Introduces a resolver pattern for retry strategies that enables per-client caching and state management. This allows multiple operations from the same client to share a single retry strategy instance, which is important for strategies that maintain state across retries such as token buckets and rate limiters.

Motivation

Previously, each operation created its own retry strategy instance, preventing state sharing across operations from the same client. This change implements a resolver-based approach.

Key Changes

  • Added a new RetryStrategyResolver protocol similar to AuthSchemeResolver. This will be used for objects which will supply clients with retry strategies.
  • Added a CachingRetryStrategyResolver which implements the protocol and returns a unique instance of a requested retry strategy object per unique combination of max attempts setting and retry mode setting. This will get called by the client when no RetryStrategy is specified.
  • Added RetryStrategyOptions for users to configure their retry strategy mode and max attempts per client call.

@SamRemis SamRemis marked this pull request as ready for review November 11, 2025 14:22
@SamRemis SamRemis requested a review from a team as a code owner November 11, 2025 14:22
nateprewitt
nateprewitt previously approved these changes Nov 15, 2025
Copy link
Contributor

@nateprewitt nateprewitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what happened with the commits for the last change but once that's fixed this should be set.

nateprewitt
nateprewitt previously approved these changes Nov 17, 2025
Comment on lines 50 to 59
case "simple":
if max_attempts is None:
return SimpleRetryStrategy()
else:
return SimpleRetryStrategy(max_attempts=max_attempts)
case "standard":
if max_attempts is None:
return StandardRetryStrategy()
else:
return StandardRetryStrategy(max_attempts=max_attempts)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a bit awkward and easy to miss when adding new ones. Can we create a single kwargs list and pass it in to avoid the conditional swap for every method?

Copy link
Contributor Author

@SamRemis SamRemis Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Before I added the typehint to the kwargs variable, pyright raised errors like this:
Argument of type "int" cannot be assigned to parameter "backoff_strategy" of type "RetryBackoffStrategy | None" in function "__init__"

I didn't realize you could resolve them by adding a type hint to the kwargs variable. This seems to be an odd behavior of pyright - taking an untyped dictionary that is being unpacked and assuming that the keys might be passed to any given input parameter seems odd.

- Add retry mode resolver functionality with caching
- Change default retry mode from simple to standard
- Add deepcopy support to retry strategies
- Update test coverage for new features

# Conflicts:
#	packages/smithy-core/tests/unit/test_retries.py
@SamRemis SamRemis force-pushed the retry-mode-resolver branch from 66eb7aa to f88f07f Compare November 20, 2025 00:14
Co-authored-by: Nate Prewitt <nate.prewitt@gmail.com>
@SamRemis SamRemis merged commit 12af0f3 into smithy-lang:develop Nov 20, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants