google_cloud_gax/
options.rs1use crate::backoff_policy::{BackoffPolicy, BackoffPolicyArg};
29use crate::polling_backoff_policy::{PollingBackoffPolicy, PollingBackoffPolicyArg};
30use crate::polling_error_policy::{PollingErrorPolicy, PollingErrorPolicyArg};
31use crate::retry_policy::{RetryPolicy, RetryPolicyArg};
32use crate::retry_throttler::{RetryThrottlerArg, SharedRetryThrottler};
33use std::sync::Arc;
34
35#[derive(Clone, Debug, Default)]
43pub struct RequestOptions {
44 idempotent: Option<bool>,
45 user_agent: Option<String>,
46 attempt_timeout: Option<std::time::Duration>,
47 retry_policy: Option<Arc<dyn RetryPolicy>>,
48 backoff_policy: Option<Arc<dyn BackoffPolicy>>,
49 retry_throttler: Option<SharedRetryThrottler>,
50 polling_error_policy: Option<Arc<dyn PollingErrorPolicy>>,
51 polling_backoff_policy: Option<Arc<dyn PollingBackoffPolicy>>,
52}
53
54impl RequestOptions {
55 pub fn idempotent(&self) -> Option<bool> {
57 self.idempotent
58 }
59
60 pub fn set_idempotency(&mut self, value: bool) {
72 self.idempotent = Some(value);
73 }
74
75 pub(crate) fn set_default_idempotency(&mut self, default: bool) {
81 self.idempotent.get_or_insert(default);
82 }
83
84 pub fn set_user_agent<T: Into<String>>(&mut self, v: T) {
86 self.user_agent = Some(v.into());
87 }
88
89 pub fn user_agent(&self) -> &Option<String> {
91 &self.user_agent
92 }
93
94 pub fn set_attempt_timeout<T: Into<std::time::Duration>>(&mut self, v: T) {
99 self.attempt_timeout = Some(v.into());
100 }
101
102 pub fn attempt_timeout(&self) -> &Option<std::time::Duration> {
104 &self.attempt_timeout
105 }
106
107 pub fn retry_policy(&self) -> &Option<Arc<dyn RetryPolicy>> {
109 &self.retry_policy
110 }
111
112 pub fn set_retry_policy<V: Into<RetryPolicyArg>>(&mut self, v: V) {
114 self.retry_policy = Some(v.into().0);
115 }
116
117 pub fn backoff_policy(&self) -> &Option<Arc<dyn BackoffPolicy>> {
119 &self.backoff_policy
120 }
121
122 pub fn set_backoff_policy<V: Into<BackoffPolicyArg>>(&mut self, v: V) {
124 self.backoff_policy = Some(v.into().0);
125 }
126
127 pub fn retry_throttler(&self) -> &Option<SharedRetryThrottler> {
129 &self.retry_throttler
130 }
131
132 pub fn set_retry_throttler<V: Into<RetryThrottlerArg>>(&mut self, v: V) {
134 self.retry_throttler = Some(v.into().0);
135 }
136
137 pub fn polling_error_policy(&self) -> &Option<Arc<dyn PollingErrorPolicy>> {
139 &self.polling_error_policy
140 }
141
142 pub fn set_polling_error_policy<V: Into<PollingErrorPolicyArg>>(&mut self, v: V) {
144 self.polling_error_policy = Some(v.into().0);
145 }
146
147 pub fn polling_backoff_policy(&self) -> &Option<Arc<dyn PollingBackoffPolicy>> {
149 &self.polling_backoff_policy
150 }
151
152 pub fn set_polling_backoff_policy<V: Into<PollingBackoffPolicyArg>>(&mut self, v: V) {
154 self.polling_backoff_policy = Some(v.into().0);
155 }
156}
157
158pub trait RequestOptionsBuilder: internal::RequestBuilder {
165 fn with_idempotency(self, v: bool) -> Self;
167
168 fn with_user_agent<V: Into<String>>(self, v: V) -> Self;
170
171 fn with_attempt_timeout<V: Into<std::time::Duration>>(self, v: V) -> Self;
176
177 fn with_retry_policy<V: Into<RetryPolicyArg>>(self, v: V) -> Self;
179
180 fn with_backoff_policy<V: Into<BackoffPolicyArg>>(self, v: V) -> Self;
182
183 fn with_retry_throttler<V: Into<RetryThrottlerArg>>(self, v: V) -> Self;
185
186 fn with_polling_error_policy<V: Into<PollingErrorPolicyArg>>(self, v: V) -> Self;
188
189 fn with_polling_backoff_policy<V: Into<PollingBackoffPolicyArg>>(self, v: V) -> Self;
191}
192
193#[cfg_attr(not(feature = "_internal-semver"), doc(hidden))]
194pub mod internal {
195 use super::RequestOptions;
200
201 pub trait RequestBuilder {
207 fn request_options(&mut self) -> &mut RequestOptions;
208 }
209
210 pub fn set_default_idempotency(mut options: RequestOptions, default: bool) -> RequestOptions {
211 options.set_default_idempotency(default);
212 options
213 }
214}
215
216impl<T> RequestOptionsBuilder for T
218where
219 T: internal::RequestBuilder,
220{
221 fn with_idempotency(mut self, v: bool) -> Self {
222 self.request_options().set_idempotency(v);
223 self
224 }
225
226 fn with_user_agent<V: Into<String>>(mut self, v: V) -> Self {
227 self.request_options().set_user_agent(v);
228 self
229 }
230
231 fn with_attempt_timeout<V: Into<std::time::Duration>>(mut self, v: V) -> Self {
232 self.request_options().set_attempt_timeout(v);
233 self
234 }
235
236 fn with_retry_policy<V: Into<RetryPolicyArg>>(mut self, v: V) -> Self {
237 self.request_options().set_retry_policy(v);
238 self
239 }
240
241 fn with_backoff_policy<V: Into<BackoffPolicyArg>>(mut self, v: V) -> Self {
242 self.request_options().set_backoff_policy(v);
243 self
244 }
245
246 fn with_retry_throttler<V: Into<RetryThrottlerArg>>(mut self, v: V) -> Self {
247 self.request_options().set_retry_throttler(v);
248 self
249 }
250
251 fn with_polling_error_policy<V: Into<PollingErrorPolicyArg>>(mut self, v: V) -> Self {
252 self.request_options().set_polling_error_policy(v);
253 self
254 }
255
256 fn with_polling_backoff_policy<V: Into<PollingBackoffPolicyArg>>(mut self, v: V) -> Self {
257 self.request_options().set_polling_backoff_policy(v);
258 self
259 }
260}
261
262#[cfg(test)]
263mod test {
264 use super::internal::*;
265 use super::*;
266 use crate::exponential_backoff::ExponentialBackoffBuilder;
267 use crate::polling_error_policy;
268 use crate::retry_policy::LimitedAttemptCount;
269 use crate::retry_throttler::AdaptiveThrottler;
270 use std::time::Duration;
271 type Result = std::result::Result<(), Box<dyn std::error::Error>>;
272
273 #[derive(Debug, Default)]
274 struct TestBuilder {
275 request_options: RequestOptions,
276 }
277 impl RequestBuilder for TestBuilder {
278 fn request_options(&mut self) -> &mut RequestOptions {
279 &mut self.request_options
280 }
281 }
282
283 #[test]
284 fn request_options() {
285 let mut opts = RequestOptions::default();
286
287 assert_eq!(opts.idempotent, None);
288 opts.set_idempotency(true);
289 assert_eq!(opts.idempotent(), Some(true));
290 opts.set_idempotency(false);
291 assert_eq!(opts.idempotent(), Some(false));
292
293 opts.set_user_agent("test-only");
294 assert_eq!(opts.user_agent().as_deref(), Some("test-only"));
295 assert_eq!(opts.attempt_timeout(), &None);
296
297 let d = Duration::from_secs(123);
298 opts.set_attempt_timeout(d);
299 assert_eq!(opts.user_agent().as_deref(), Some("test-only"));
300 assert_eq!(opts.attempt_timeout(), &Some(d));
301
302 opts.set_retry_policy(LimitedAttemptCount::new(3));
303 assert!(opts.retry_policy().is_some(), "{opts:?}");
304
305 opts.set_backoff_policy(ExponentialBackoffBuilder::new().clamp());
306 assert!(opts.backoff_policy().is_some(), "{opts:?}");
307
308 opts.set_retry_throttler(AdaptiveThrottler::default());
309 assert!(opts.retry_throttler().is_some(), "{opts:?}");
310
311 opts.set_polling_error_policy(polling_error_policy::Aip194Strict);
312 assert!(opts.polling_error_policy().is_some(), "{opts:?}");
313
314 opts.set_polling_backoff_policy(ExponentialBackoffBuilder::new().clamp());
315 assert!(opts.polling_backoff_policy().is_some(), "{opts:?}");
316 }
317
318 #[test]
319 fn request_options_idempotency() {
320 let opts = set_default_idempotency(RequestOptions::default(), true);
321 assert_eq!(opts.idempotent(), Some(true));
322 let opts = set_default_idempotency(opts, false);
323 assert_eq!(opts.idempotent(), Some(true));
324
325 let opts = set_default_idempotency(RequestOptions::default(), false);
326 assert_eq!(opts.idempotent(), Some(false));
327 let opts = set_default_idempotency(opts, true);
328 assert_eq!(opts.idempotent(), Some(false));
329 }
330
331 #[test]
332 fn request_options_builder() -> Result {
333 let mut builder = TestBuilder::default();
334 assert_eq!(builder.request_options().user_agent(), &None);
335 assert_eq!(builder.request_options().attempt_timeout(), &None);
336
337 let mut builder = TestBuilder::default().with_idempotency(true);
338 assert_eq!(builder.request_options().idempotent(), Some(true));
339 let mut builder = TestBuilder::default().with_idempotency(false);
340 assert_eq!(builder.request_options().idempotent(), Some(false));
341
342 let mut builder = TestBuilder::default().with_user_agent("test-only");
343 assert_eq!(
344 builder.request_options().user_agent().as_deref(),
345 Some("test-only")
346 );
347 assert_eq!(builder.request_options().attempt_timeout(), &None);
348
349 let d = Duration::from_secs(123);
350 let mut builder = TestBuilder::default().with_attempt_timeout(d);
351 assert_eq!(builder.request_options().user_agent(), &None);
352 assert_eq!(builder.request_options().attempt_timeout(), &Some(d));
353
354 let mut builder = TestBuilder::default().with_retry_policy(LimitedAttemptCount::new(3));
355 assert!(
356 builder.request_options().retry_policy().is_some(),
357 "{builder:?}"
358 );
359
360 let mut builder =
361 TestBuilder::default().with_backoff_policy(ExponentialBackoffBuilder::new().build()?);
362 assert!(
363 builder.request_options().backoff_policy().is_some(),
364 "{builder:?}"
365 );
366
367 let mut builder = TestBuilder::default().with_retry_throttler(AdaptiveThrottler::default());
368 assert!(
369 builder.request_options().retry_throttler().is_some(),
370 "{builder:?}"
371 );
372
373 let mut builder =
374 TestBuilder::default().with_polling_error_policy(polling_error_policy::Aip194Strict);
375 assert!(
376 builder.request_options().polling_error_policy().is_some(),
377 "{builder:?}"
378 );
379
380 let mut builder = TestBuilder::default()
381 .with_polling_backoff_policy(ExponentialBackoffBuilder::new().build()?);
382 assert!(
383 builder.request_options().polling_backoff_policy().is_some(),
384 "{builder:?}"
385 );
386
387 Ok(())
388 }
389}