amazon_spapi/apis/
configuration.rs

1use reqwest::{retry, Client, Error, Request, Response};
2use std::{cell::RefCell, ops::Deref};
3
4#[derive(Debug, Clone)]
5pub struct CustomClient {
6    inner: Client,
7    retry_count: usize,
8}
9
10impl CustomClient {
11    pub fn new(client: Client, retry_count: usize) -> Self {
12        Self { inner: client, retry_count }
13    }
14
15    pub async fn execute(&self, request: Request) -> Result<Response, Error> {
16        log::debug!("Executing request to: {}", request.url());
17        log::debug!("Executing request method: {}", request.method());
18        log::debug!("Executing request headers: {:?}", request.headers());
19        log::debug!("Executing request body: {:?}", request.body());
20
21        if self.retry_count == 0 {
22            let result = self.inner.execute(request).await;
23            log::debug!("Response status: {:?}", result.as_ref().map(|r| r.status()));
24            log::debug!(
25                "Response headers: {:?}",
26                result.as_ref().map(|r| r.headers())
27            );
28            return result;
29        } else {
30            let mut last_result = None;
31
32            for i in 0..self.retry_count {
33                // Clone the request for retry attempts
34                let request_clone = match request.try_clone() {
35                    Some(req) => req,
36                    None => {
37                        // If we can't clone the request, return the result of the original request
38                        return self.inner.execute(request).await;
39                    }
40                };
41
42                let result = self.inner.execute(request_clone).await;
43
44                match &result {
45                    Ok(response) => {
46                        let status = response.status();
47                        // If status is 429, sleep and retry
48                        if status == reqwest::StatusCode::TOO_MANY_REQUESTS {
49                            log::warn!(
50                                "Received 429 status, retrying in {} seconds (attempt {}/{})",
51                                (i + 1) * 2,
52                                i + 1,
53                                self.retry_count
54                            );
55                            tokio::time::sleep(tokio::time::Duration::from_secs(((i + 1) * 2) as u64)).await;
56                            last_result = Some(result);
57                            continue;
58                        } else {
59                            // For other statuses, return the result immediately
60                            return result;
61                        }
62                    }
63                    Err(_) => {
64                        // Request error, return immediately
65                        return result;
66                    }
67                }
68            }
69
70            // If all retries exhausted, return the last result or execute the original request as a fallback
71            match last_result {
72                Some(res) => res,
73                None => self.inner.execute(request).await,
74            }
75        }
76    }
77}
78
79impl Deref for CustomClient {
80    type Target = Client;
81
82    fn deref(&self) -> &Self::Target {
83        &self.inner
84    }
85}
86
87#[derive(Debug, Clone)]
88pub struct Configuration {
89    pub base_path: String,
90    pub user_agent: Option<String>,
91    pub client: CustomClient,
92}