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
Comment on lines +114 to +122
class RetryStrategyResolver[RS: RetryStrategy](Protocol):
"""Used to resolve a RetryStrategy from retry options."""

async def resolve_retry_strategy(self, *, options: RetryStrategyOptions) -> RS:
"""Resolve the retry strategy from the provided options.
:param options: The retry strategy options to use for creating the strategy.
"""
...
Copy link
Contributor

Choose a reason for hiding this comment

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

What other kinds of RetryStrategyResolver are we envisioning? This seems like it only has one real use which is to create a RetryStrategy if one isn't provided.

"""

def __init__(self) -> None:
self._cache: dict[RetryStrategyOptions, RetryStrategy] = {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there an advantage to us maintaining the cache ourselves vs using something like Python's lru_cache?

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