#[cfg(feature = "alloc")]
use crate::compat::Box;
use crate::compat::Duration;
use crate::predicate;
#[cfg(feature = "alloc")]
use crate::predicate::Predicate;
use crate::stop;
#[cfg(feature = "alloc")]
use crate::stop::Stop;
use crate::wait;
#[cfg(feature = "alloc")]
use crate::wait::Wait;
const DEFAULT_MAX_ATTEMPTS: u32 = 3;
const DEFAULT_INITIAL_WAIT: Duration = Duration::from_millis(100);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RetryPolicy<
S = stop::StopAfterAttempts,
W = wait::WaitExponential,
P = predicate::PredicateAnyError,
> {
stop: S,
wait: W,
predicate: P,
}
impl RetryPolicy<stop::StopAfterAttempts, wait::WaitExponential, predicate::PredicateAnyError> {
#[must_use]
pub fn new() -> Self {
RetryPolicy {
stop: stop::attempts(DEFAULT_MAX_ATTEMPTS),
wait: wait::exponential(DEFAULT_INITIAL_WAIT),
predicate: predicate::any_error(),
}
}
}
impl Default
for RetryPolicy<stop::StopAfterAttempts, wait::WaitExponential, predicate::PredicateAnyError>
{
fn default() -> Self {
Self::new()
}
}
impl<S, W, P> RetryPolicy<S, W, P> {
#[must_use]
pub fn stop<NewStop>(self, stop: NewStop) -> RetryPolicy<NewStop, W, P> {
RetryPolicy {
stop,
wait: self.wait,
predicate: self.predicate,
}
}
#[must_use]
pub fn wait<NewWait>(self, wait: NewWait) -> RetryPolicy<S, NewWait, P> {
RetryPolicy {
stop: self.stop,
wait,
predicate: self.predicate,
}
}
#[must_use]
pub fn when<NewPredicate>(self, predicate: NewPredicate) -> RetryPolicy<S, W, NewPredicate> {
RetryPolicy {
stop: self.stop,
wait: self.wait,
predicate,
}
}
#[must_use]
pub fn until<NewPredicate>(
self,
predicate: NewPredicate,
) -> RetryPolicy<S, W, predicate::PredicateUntil<NewPredicate>> {
RetryPolicy {
stop: self.stop,
wait: self.wait,
predicate: predicate::until(predicate),
}
}
#[cfg(feature = "alloc")]
#[must_use]
#[allow(clippy::type_complexity)]
pub fn boxed<T, E>(
self,
) -> RetryPolicy<
Box<dyn Stop + Send + 'static>,
Box<dyn Wait + Send + 'static>,
Box<dyn Predicate<T, E> + Send + 'static>,
>
where
S: Stop + Send + 'static,
W: Wait + Send + 'static,
P: Predicate<T, E> + Send + 'static,
{
RetryPolicy {
stop: Box::new(self.stop),
wait: Box::new(self.wait),
predicate: Box::new(self.predicate),
}
}
#[cfg(feature = "alloc")]
#[must_use]
#[allow(clippy::type_complexity)]
pub fn boxed_local<T, E>(
self,
) -> RetryPolicy<
Box<dyn Stop + 'static>,
Box<dyn Wait + 'static>,
Box<dyn Predicate<T, E> + 'static>,
>
where
S: Stop + 'static,
W: Wait + 'static,
P: Predicate<T, E> + 'static,
{
RetryPolicy {
stop: Box::new(self.stop),
wait: Box::new(self.wait),
predicate: Box::new(self.predicate),
}
}
}
pub(crate) trait PolicyHandle<S, W, P> {
fn policy_ref(&self) -> &RetryPolicy<S, W, P>;
}
impl<S, W, P> PolicyHandle<S, W, P> for RetryPolicy<S, W, P> {
fn policy_ref(&self) -> &RetryPolicy<S, W, P> {
self
}
}
impl<S, W, P> PolicyHandle<S, W, P> for &RetryPolicy<S, W, P> {
fn policy_ref(&self) -> &RetryPolicy<S, W, P> {
self
}
}
macro_rules! impl_alloc_hook_chain {
(
impl[$($gen:tt)*] $Builder:ty
$(where { $($wc:tt)* })? =>
before_attempt -> { $($ba:tt)* },
after_attempt -> { $($aa:tt)* },
on_exit -> { $($ox:tt)* } $(,)?
) => {
#[cfg(feature = "alloc")]
#[allow(clippy::type_complexity)]
impl<$($gen)*> $Builder
$(where $($wc)*)?
{
#[must_use]
pub fn before_attempt<Hook>(
self,
hook: Hook,
) -> $($ba)*
where
Hook: FnMut(&RetryState),
{
self.map_hooks(|hooks| hooks.chain_before_attempt(hook))
}
#[must_use]
pub fn after_attempt<Hook>(
self,
hook: Hook,
) -> $($aa)*
where
Hook: for<'a> FnMut(&AttemptState<'a, T, E>),
{
self.map_hooks(|hooks| hooks.chain_after_attempt(hook))
}
#[must_use]
pub fn on_exit<Hook>(
self,
hook: Hook,
) -> $($ox)*
where
Hook: for<'a> FnMut(&ExitState<'a, T, E>),
{
self.map_hooks(|hooks| hooks.chain_on_exit(hook))
}
}
};
}
mod execution;
mod ext;
mod time;
pub use execution::async_exec::{AsyncRetry, AsyncRetryWithStats, NoAsyncSleep};
#[cfg(feature = "alloc")]
pub(crate) use execution::hooks::HookChain;
pub(crate) use execution::hooks::{AttemptHook, BeforeAttemptHook, ExecutionHooks, ExitHook};
pub use execution::sync_exec::NoSyncSleep;
pub use execution::sync_exec::{SyncRetry, SyncRetryWithStats};
pub use ext::{
AsyncRetryBuilder, AsyncRetryBuilderWithStats, AsyncRetryExt, DefaultAsyncRetryBuilder,
DefaultAsyncRetryBuilderWithStats, DefaultSyncRetryBuilder, DefaultSyncRetryBuilderWithStats,
RetryExt, SyncRetryBuilder, SyncRetryBuilderWithStats,
};