mirror of
https://github.com/TrueLayer/reqwest-middleware.git
synced 2024-12-26 19:06:31 +00:00
fix recursion in retry (#49)
This commit is contained in:
parent
ad18935d1f
commit
b3f7ce40d3
1 changed files with 11 additions and 29 deletions
|
@ -58,33 +58,22 @@ impl<T: RetryPolicy + Send + Sync> Middleware for RetryTransientMiddleware<T> {
|
||||||
// downstream. This will guard against previous retries poluting `Extensions`.
|
// downstream. This will guard against previous retries poluting `Extensions`.
|
||||||
// That is, we only return what's populated in the typemap for the last retry attempt
|
// That is, we only return what's populated in the typemap for the last retry attempt
|
||||||
// and copy those into the the `global` Extensions map.
|
// and copy those into the the `global` Extensions map.
|
||||||
self.execute_with_retry_recursive(req, next, extensions, 0)
|
self.execute_with_retry(req, next, extensions).await
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RetryPolicy + Send + Sync> RetryTransientMiddleware<T> {
|
impl<T: RetryPolicy + Send + Sync> RetryTransientMiddleware<T> {
|
||||||
/// **RECURSIVE**.
|
|
||||||
///
|
|
||||||
/// SAFETY: The condition for termination is the number of retries
|
|
||||||
/// set on the `RetryOption` object which is capped to 10 therefore
|
|
||||||
/// we can know that this will not cause a overflow of the stack.
|
|
||||||
///
|
|
||||||
/// This function will try to execute the request, if it fails
|
/// This function will try to execute the request, if it fails
|
||||||
/// with an error classified as transient it will call itself
|
/// with an error classified as transient it will call itself
|
||||||
/// to retry the request.
|
/// to retry the request.
|
||||||
///
|
async fn execute_with_retry<'a>(
|
||||||
/// NOTE: This function is not async because calling an async function
|
|
||||||
/// recursively is not allowed.
|
|
||||||
///
|
|
||||||
fn execute_with_retry_recursive<'a>(
|
|
||||||
&'a self,
|
&'a self,
|
||||||
req: Request,
|
req: Request,
|
||||||
next: Next<'a>,
|
next: Next<'a>,
|
||||||
ext: &'a mut Extensions,
|
ext: &'a mut Extensions,
|
||||||
n_past_retries: u32,
|
) -> Result<Response> {
|
||||||
) -> futures::future::BoxFuture<'a, Result<Response>> {
|
let mut n_past_retries = 0;
|
||||||
Box::pin(async move {
|
loop {
|
||||||
// Cloning the request object before-the-fact is not ideal..
|
// Cloning the request object before-the-fact is not ideal..
|
||||||
// However, if the body of the request is not static, e.g of type `Bytes`,
|
// However, if the body of the request is not static, e.g of type `Bytes`,
|
||||||
// the Clone operation should be of constant complexity and not O(N)
|
// the Clone operation should be of constant complexity and not O(N)
|
||||||
|
@ -95,13 +84,11 @@ impl<T: RetryPolicy + Send + Sync> RetryTransientMiddleware<T> {
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let cloned_next = next.clone();
|
let result = next.clone().run(duplicate_request, ext).await;
|
||||||
|
|
||||||
let result = next.run(req, ext).await;
|
|
||||||
|
|
||||||
// We classify the response which will return None if not
|
// We classify the response which will return None if not
|
||||||
// errors were returned.
|
// errors were returned.
|
||||||
match Retryable::from_reqwest_response(&result) {
|
break match Retryable::from_reqwest_response(&result) {
|
||||||
Some(retryable)
|
Some(retryable)
|
||||||
if retryable == Retryable::Transient
|
if retryable == Retryable::Transient
|
||||||
&& n_past_retries < MAXIMUM_NUMBER_OF_RETRIES =>
|
&& n_past_retries < MAXIMUM_NUMBER_OF_RETRIES =>
|
||||||
|
@ -121,19 +108,14 @@ impl<T: RetryPolicy + Send + Sync> RetryTransientMiddleware<T> {
|
||||||
);
|
);
|
||||||
tokio::time::sleep(duration).await;
|
tokio::time::sleep(duration).await;
|
||||||
|
|
||||||
self.execute_with_retry_recursive(
|
n_past_retries += 1;
|
||||||
duplicate_request,
|
continue;
|
||||||
cloned_next,
|
|
||||||
ext,
|
|
||||||
n_past_retries + 1,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
} else {
|
} else {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(_) | None => result,
|
Some(_) | None => result,
|
||||||
}
|
};
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue