use reqwest::{retry, Client, Error, Request, Response};
use std::{cell::RefCell, ops::Deref};
#[derive(Debug, Clone)]
pub struct CustomClient {
inner: Client,
retry_count: usize,
}
impl CustomClient {
pub fn new(client: Client, retry_count: usize) -> Self {
Self { inner: client, retry_count }
}
pub async fn execute(&self, request: Request) -> Result<Response, Error> {
log::debug!("Executing request to: {}", request.url());
log::debug!("Executing request method: {}", request.method());
log::debug!("Executing request headers: {:?}", request.headers());
log::debug!("Executing request body: {:?}", request.body());
if self.retry_count == 0 {
let result = self.inner.execute(request).await;
log::debug!("Response status: {:?}", result.as_ref().map(|r| r.status()));
log::debug!(
"Response headers: {:?}",
result.as_ref().map(|r| r.headers())
);
return result;
} else {
let mut last_result = None;
for i in 0..self.retry_count {
let request_clone = match request.try_clone() {
Some(req) => req,
None => {
return self.inner.execute(request).await;
}
};
let result = self.inner.execute(request_clone).await;
match &result {
Ok(response) => {
let status = response.status();
if status == reqwest::StatusCode::TOO_MANY_REQUESTS {
log::warn!(
"Received 429 status, retrying in {} seconds (attempt {}/{})",
(i + 1) * 2,
i + 1,
self.retry_count
);
tokio::time::sleep(tokio::time::Duration::from_secs(((i + 1) * 2) as u64)).await;
last_result = Some(result);
continue;
} else {
return result;
}
}
Err(_) => {
return result;
}
}
}
match last_result {
Some(res) => res,
None => self.inner.execute(request).await,
}
}
}
}
impl Deref for CustomClient {
type Target = Client;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Debug, Clone)]
pub struct Configuration {
pub base_path: String,
pub user_agent: Option<String>,
pub client: CustomClient,
}