google_cloud_storage/storage/
request_options.rs1use super::common_options::CommonOptions;
18use crate::{
19 read_resume_policy::ReadResumePolicy,
20 storage::checksum::details::{Checksum, Crc32c},
21};
22use gaxi::options::ClientConfig;
23use google_cloud_gax::{
24 backoff_policy::BackoffPolicy,
25 retry_policy::RetryPolicy,
26 retry_throttler::{AdaptiveThrottler, SharedRetryThrottler},
27};
28use std::sync::{Arc, Mutex};
29use std::time::Duration;
30
31const DEFAULT_BIDI_ATTEMPT_TIMEOUT: Duration = Duration::from_secs(60);
33
34#[derive(Clone, Debug)]
39pub struct RequestOptions {
40 pub(crate) retry_policy: Arc<dyn RetryPolicy>,
41 pub(crate) backoff_policy: Arc<dyn BackoffPolicy>,
42 pub(crate) retry_throttler: SharedRetryThrottler,
43 pub(crate) idempotency: Option<bool>,
44 pub(crate) checksum: Checksum,
45 pub(crate) automatic_decompression: bool,
46 pub(crate) common_options: CommonOptions,
47 pub(crate) bidi_attempt_timeout: Duration,
48 pub(crate) user_agent: Option<String>,
49 pub(crate) quota_project: Option<String>,
50}
51
52impl RequestOptions {
53 pub(crate) fn new() -> Self {
54 let retry_policy = Arc::new(crate::retry_policy::storage_default());
55 let backoff_policy = Arc::new(crate::backoff_policy::default());
56 let retry_throttler = Arc::new(Mutex::new(AdaptiveThrottler::default()));
57 Self::new_with_policies(
58 retry_policy,
59 backoff_policy,
60 retry_throttler,
61 CommonOptions::new(),
62 )
63 }
64
65 pub(crate) fn new_with_client_config(
66 config: &ClientConfig,
67 common_options: CommonOptions,
68 ) -> Self {
69 let retry_policy = config
70 .retry_policy
71 .clone()
72 .unwrap_or_else(|| Arc::new(crate::retry_policy::storage_default()));
73 let backoff_policy = config
74 .backoff_policy
75 .clone()
76 .unwrap_or_else(|| Arc::new(crate::backoff_policy::default()));
77 let retry_throttler = config.retry_throttler.clone();
78 Self::new_with_policies(
79 retry_policy,
80 backoff_policy,
81 retry_throttler,
82 common_options,
83 )
84 }
85
86 pub fn set_read_resume_policy(&mut self, v: Arc<dyn ReadResumePolicy>) {
88 self.common_options.read_resume_policy = v;
89 }
90
91 pub fn read_resume_policy(&self) -> Arc<dyn ReadResumePolicy> {
93 self.common_options.read_resume_policy.clone()
94 }
95
96 pub fn set_resumable_upload_threshold(&mut self, v: usize) {
98 self.common_options.resumable_upload_threshold = v;
99 }
100
101 pub fn resumable_upload_threshold(&self) -> usize {
103 self.common_options.resumable_upload_threshold
104 }
105
106 pub fn set_resumable_upload_buffer_size(&mut self, v: usize) {
108 self.common_options.resumable_upload_buffer_size = v;
109 }
110
111 pub fn set_bidi_attempt_timeout(&mut self, v: Duration) {
113 self.bidi_attempt_timeout = v;
114 }
115
116 pub fn resumable_upload_buffer_size(&self) -> usize {
118 self.common_options.resumable_upload_buffer_size
119 }
120
121 pub fn with_user_agent(&mut self, v: impl Into<String>) {
123 self.user_agent = Some(v.into());
124 }
125
126 pub fn set_quota_project(&mut self, v: impl Into<String>) {
128 self.quota_project = Some(v.into());
129 }
130
131 fn new_with_policies(
132 retry_policy: Arc<dyn RetryPolicy>,
133 backoff_policy: Arc<dyn BackoffPolicy>,
134 retry_throttler: SharedRetryThrottler,
135 common_options: CommonOptions,
136 ) -> Self {
137 Self {
138 retry_policy,
139 backoff_policy,
140 retry_throttler,
141 common_options,
142 idempotency: None,
143 checksum: Checksum {
144 crc32c: Some(Crc32c::default()),
145 md5_hash: None,
146 },
147 automatic_decompression: false,
148 bidi_attempt_timeout: DEFAULT_BIDI_ATTEMPT_TIMEOUT,
149 user_agent: None,
150 quota_project: None,
151 }
152 }
153
154 pub(crate) fn gax(&self) -> google_cloud_gax::options::RequestOptions {
155 let mut options = google_cloud_gax::options::RequestOptions::default();
156 options.set_backoff_policy(self.backoff_policy.clone());
157 options.set_retry_policy(self.retry_policy.clone());
158 options.set_retry_throttler(self.retry_throttler.clone());
159 if let Some(i) = &self.idempotency {
160 options.set_idempotency(*i);
161 }
162 if let Some(s) = &self.user_agent {
163 options.set_user_agent(s);
164 }
165 if let Some(up) = &self.quota_project {
166 options.set_quota_project(up.clone());
167 }
168 options
169 }
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175 use crate::storage::client::tests::{MockBackoffPolicy, MockRetryPolicy, MockRetryThrottler};
176
177 #[test]
178 fn gax_policies() {
179 let mut options = RequestOptions::new();
180 options.retry_policy = Arc::new(MockRetryPolicy::new());
181 options.retry_throttler = Arc::new(Mutex::new(MockRetryThrottler::new()));
182 options.backoff_policy = Arc::new(MockBackoffPolicy::new());
183
184 let got = options.gax();
185 assert!(got.backoff_policy().is_some(), "{got:?}");
186 assert!(got.retry_policy().is_some(), "{got:?}");
187 assert!(got.retry_throttler().is_some(), "{got:?}");
188 assert!(got.idempotent().is_none(), "{got:?}");
189
190 let fmt = format!("{got:?}");
191 assert!(fmt.contains("MockBackoffPolicy"), "{fmt}");
192 assert!(fmt.contains("MockRetryPolicy"), "{fmt}");
193 assert!(fmt.contains("MockRetryThrottler"), "{fmt}");
194 }
195
196 #[test]
197 fn gax_idempotency() {
198 let mut options = RequestOptions::new();
199 options.idempotency = Some(true);
200 let got = options.gax();
201 assert_eq!(got.idempotent(), Some(true));
202 }
203
204 #[test]
205 fn gax_user_agent() {
206 let user_agent = "quick_foxes_lazy_dogs/1.2.3";
207 let mut options = RequestOptions::new();
208 options.with_user_agent(user_agent);
209 let got = options.gax();
210 assert_eq!(got.user_agent().as_deref(), Some(user_agent));
211 }
212
213 #[test]
214 fn gax_quota_project() {
215 const PROJECT_NAME: &str = "project_lazy_dog";
216 let mut options = RequestOptions::new();
217 options.set_quota_project(PROJECT_NAME);
218 let got = options.gax();
219 assert_eq!(got.quota_project().as_deref(), Some(PROJECT_NAME));
220 }
221}