Make TokenBucket and ClientRateLimiter configurable#4263
Conversation
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
| #[non_exhaustive] | ||
| #[derive(Clone, Debug, Hash, PartialEq, Eq)] | ||
| #[derive(Clone, Debug)] | ||
| pub struct RetryPartition { |
There was a problem hiding this comment.
This still leaves the possibility that a user creating two different clients that wants to assign them different token buckets or rate limiters results in "first access wins" right?
e.g.
// configure client 1 with custom token bucket
let client1 = Client::builder().retry_partition(RetryPartition::custom("part1").token_bucket(...).build());
// configure second client with different token bucket but same partition name
let client2 = Client::builder().retry_partition(RetryPartition::custom("part1").token_bucket(...).build());It may not be obvious that client2 will never use the given token bucket.
I'm not necessarily saying we shouldn't do this I'm just trying to understand the sharp edges of this approach (all of the approaches discussed have some sort of sharp edge). Also wondering how to best mitigate this if possible.
There was a problem hiding this comment.
two different clients that wants to assign them different token buckets or rate limiters results in "first access wins" right?
Yeah, this is just like any other configurations. Instead of sharing a config value, if two clients are provided a separate config value, whichever makes to the config bag wins.
There was a problem hiding this comment.
8118cab clarifies the rustdoc per this discussion.
There was a problem hiding this comment.
Alternatively, we can consider changing RetryPartitionInner to be
pub(crate) enum RetryPartitionInner {
Named(Cow<'static, str>),
Anonymous {
token_bucket: Option<TokenBucket>,
client_rate_limiter: Option<ClientRateLimiter>,
},
}
Anonymous RetryPartitions aren't equal to each other (just like anonymous functions are all different). This way, customers cannot give a name and it may help avoid confusion that they are different even though they have the same custom partition names.
EDIT:
Since RetryPartition implements the Hash trait, the Anonymous variant needs some sort of unique ID, something like
pub(crate) enum RetryPartitionInner {
Named(Cow<'static, str>),
Anonymous {
_id: Arc<()>, // cloned `RetryPartition::Anonymous`s are equal
token_bucket: Option<TokenBucket>,
client_rate_limiter: Option<ClientRateLimiter>,
},
}
There was a problem hiding this comment.
Hmm need to think on this, that may be worth considering. Let's discuss offline.
rust-runtime/aws-smithy-runtime/src/client/retries/client_rate_limiter.rs
Outdated
Show resolved
Hide resolved
rust-runtime/aws-smithy-runtime/src/client/retries/token_bucket.rs
Outdated
Show resolved
Hide resolved
rust-runtime/aws-smithy-runtime/src/client/retries/token_bucket.rs
Outdated
Show resolved
Hide resolved
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
This commit is based on #4263 (comment)
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
This commit addresses #4263 (comment)
This commit addresses #4263 (comment)
This commit addresses #4263 (comment)
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
Motivation and Context
The SDK provides basic retry configuration through the RetryConfig struct, allowing users to set parameters like retry mode, maximum attempts, and backoff durations. However, there has been a need for more advanced configuration options, particularly for token buckets and adaptive rate limiting.
Description
This PR makes
TokenBucketandClientRateLimiterconfigurable through the RetryPartition struct.In most cases, a "default"
RetryPartitionis used whereTokenBucketandClientRateLimiterare constructed behind the scenes and registered in static maps. If a customer wishes to configure aTokenBucketand/orClientRateLimiter, it can be done by a customRetryPartition:For more details, refer to the API docs on the setter and the RetryPartition struct itself.
End-to-end customer experience
Customers can use a custom partition with an SDK like so
Dismissed alternatives
We considered alternative approaches for making these configurable but dismissed them for the following reasons:
Alt1: Make them configurable through
RetryConfigRetryConfigis defined inaws-smithy-typeswhereasTokenBucketandClientRateLimiterinaws-smithy-runtime. Sinceaws-smithy-typesis higher in the dependency hierarchy, it cannot depend onaws-smithy-runtimeto refer toTokenBucketandClientRateLimiter. MovingTokenBucketandClientRateLimitertoaws-smithy-typeswas probably not ideal either, as they are more closely tied to the smithy runtime.Alt2: Make them configurable through individual setters on config builder
This significantly increases the cognitive load for customers, as they see multiple configuration options at the same level.
Testing
TokenBucketinrust-runtime/aws-smithy-runtime/src/client/retries/token_bucket.rsTokenBucketandClientRateLimiterinaws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/RetryPartitionTest.kt.Checklist
.changelogdirectory, specifying "client," "server," or both in theapplies_tokey..changelogdirectory, specifying "aws-sdk-rust" in theapplies_tokey.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.