aws_smithy_runtime/client/
retries.rs1pub mod classifiers;
8
9pub mod strategy;
11
12mod client_rate_limiter;
13mod token_bucket;
14
15use aws_smithy_types::config_bag::{Storable, StoreReplace};
16use std::fmt;
17
18pub use client_rate_limiter::{
19 ClientRateLimiter, ClientRateLimiterBuilder, ClientRateLimiterPartition,
20};
21pub use token_bucket::{TokenBucket, TokenBucketBuilder};
22
23use std::borrow::Cow;
24
25#[non_exhaustive]
41#[derive(Clone, Debug)]
42pub struct RetryPartition {
43 pub(crate) inner: RetryPartitionInner,
44}
45
46#[derive(Clone, Debug)]
47pub(crate) enum RetryPartitionInner {
48 Default(Cow<'static, str>),
49 Custom {
50 name: Cow<'static, str>,
51 token_bucket: TokenBucket,
52 client_rate_limiter: ClientRateLimiter,
53 },
54}
55
56impl RetryPartition {
57 pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
59 Self {
60 inner: RetryPartitionInner::Default(name.into()),
61 }
62 }
63
64 pub fn custom(name: impl Into<Cow<'static, str>>) -> RetryPartitionBuilder {
66 RetryPartitionBuilder {
67 name: name.into(),
68 token_bucket: None,
69 client_rate_limiter: None,
70 }
71 }
72
73 fn name(&self) -> &str {
74 match &self.inner {
75 RetryPartitionInner::Default(name) => name,
76 RetryPartitionInner::Custom { name, .. } => name,
77 }
78 }
79}
80
81impl PartialEq for RetryPartition {
82 fn eq(&self, other: &Self) -> bool {
83 match (&self.inner, &other.inner) {
84 (RetryPartitionInner::Default(name1), RetryPartitionInner::Default(name2)) => {
85 name1 == name2
86 }
87 (
88 RetryPartitionInner::Custom { name: name1, .. },
89 RetryPartitionInner::Custom { name: name2, .. },
90 ) => name1 == name2,
91 _ => false,
93 }
94 }
95}
96
97impl Eq for RetryPartition {}
98
99impl std::hash::Hash for RetryPartition {
100 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
101 match &self.inner {
102 RetryPartitionInner::Default(name) => {
103 0u8.hash(state);
105 name.hash(state);
106 }
107 RetryPartitionInner::Custom { name, .. } => {
108 1u8.hash(state);
110 name.hash(state);
111 }
112 }
113 }
114}
115
116impl fmt::Display for RetryPartition {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.write_str(self.name())
119 }
120}
121
122impl Storable for RetryPartition {
123 type Storer = StoreReplace<RetryPartition>;
124}
125
126pub struct RetryPartitionBuilder {
128 name: Cow<'static, str>,
129 token_bucket: Option<TokenBucket>,
130 client_rate_limiter: Option<ClientRateLimiter>,
131}
132
133impl RetryPartitionBuilder {
134 pub fn token_bucket(mut self, token_bucket: TokenBucket) -> Self {
136 self.token_bucket = Some(token_bucket);
137 self
138 }
139
140 pub fn client_rate_limiter(mut self, client_rate_limiter: ClientRateLimiter) -> Self {
142 self.client_rate_limiter = Some(client_rate_limiter);
143 self
144 }
145
146 pub fn build(self) -> RetryPartition {
148 RetryPartition {
149 inner: RetryPartitionInner::Custom {
150 name: self.name,
151 token_bucket: self.token_bucket.unwrap_or_default(),
152 client_rate_limiter: self.client_rate_limiter.unwrap_or_default(),
153 },
154 }
155 }
156}
157#[cfg(test)]
158mod tests {
159 use super::*;
160 use std::collections::hash_map::DefaultHasher;
161 use std::hash::{Hash, Hasher};
162
163 fn hash_value<T: Hash>(t: &T) -> u64 {
164 let mut hasher = DefaultHasher::new();
165 t.hash(&mut hasher);
166 hasher.finish()
167 }
168
169 #[test]
170 fn test_retry_partition_equality() {
171 let default1 = RetryPartition::new("test");
172 let default2 = RetryPartition::new("test");
173 let default3 = RetryPartition::new("other");
174
175 let configured1 = RetryPartition::custom("test").build();
176 let configured2 = RetryPartition::custom("test").build();
177 let configured3 = RetryPartition::custom("other").build();
178
179 assert_eq!(default1, default2);
181 assert_eq!(configured1, configured2);
182
183 assert_ne!(default1, default3);
185 assert_ne!(configured1, configured3);
186
187 assert_ne!(default1, configured1);
189 }
190
191 #[test]
192 fn test_retry_partition_hash() {
193 let default = RetryPartition::new("test");
194 let configured = RetryPartition::custom("test").build();
195
196 assert_ne!(hash_value(&default), hash_value(&configured));
198
199 let default2 = RetryPartition::new("test");
201 assert_eq!(hash_value(&default), hash_value(&default2));
202 }
203}