backon/
sleep.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use core::{
    future::{Future, Ready},
    time::Duration,
};

/// A sleeper is used to generate a future that completes after a specified duration.
pub trait Sleeper: 'static {
    /// The future returned by the `sleep` method.
    type Sleep: Future<Output = ()>;

    /// Create a future that completes after a set period.
    fn sleep(&self, dur: Duration) -> Self::Sleep;
}

/// A stub trait allowing non-[`Sleeper`] types to be used as a generic parameter in [`Retry`][crate::Retry].
/// It does not provide actual functionality.
#[doc(hidden)]
pub trait MaybeSleeper: 'static {
    type Sleep: Future<Output = ()>;
}

/// All `Sleeper` will implement  `MaybeSleeper`, but not vice versa.
impl<T: Sleeper + ?Sized> MaybeSleeper for T {
    type Sleep = <T as Sleeper>::Sleep;
}

/// All `Fn(Duration) -> impl Future<Output = ()>` implements `Sleeper`.
impl<F: Fn(Duration) -> Fut + 'static, Fut: Future<Output = ()>> Sleeper for F {
    type Sleep = Fut;

    fn sleep(&self, dur: Duration) -> Self::Sleep {
        self(dur)
    }
}

/// The default implementation of `Sleeper` when no features are enabled.
///
/// It will fail to compile if a containing [`Retry`][crate::Retry] is `.await`ed without calling [`Retry::sleep`][crate::Retry::sleep] to provide a valid sleeper.
#[cfg(all(not(feature = "tokio-sleep"), not(feature = "gloo-timers-sleep"),))]
pub type DefaultSleeper = PleaseEnableAFeatureOrProvideACustomSleeper;
/// The default implementation of `Sleeper` while feature `tokio-sleep` enabled.
///
/// it uses `tokio::time::sleep`.
#[cfg(all(not(target_arch = "wasm32"), feature = "tokio-sleep"))]
pub type DefaultSleeper = TokioSleeper;
/// The default implementation of `Sleeper` while feature `gloo-timers-sleep` enabled.
///
/// It uses `gloo_timers::sleep::sleep`.
#[cfg(all(target_arch = "wasm32", feature = "gloo-timers-sleep"))]
pub type DefaultSleeper = GlooTimersSleep;

/// A placeholder type that does not implement [`Sleeper`] and will therefore fail to compile if used as one.
///
/// Users should enable a feature of this crate that provides a valid [`Sleeper`] implementation when this type appears in compilation errors. Alternatively, a custom [`Sleeper`] implementation should be provided where necessary, such as in [`crate::Retry::sleeper`].
#[doc(hidden)]
#[derive(Clone, Copy, Debug, Default)]
pub struct PleaseEnableAFeatureOrProvideACustomSleeper;

/// Implement `MaybeSleeper` but not `Sleeper`.
impl MaybeSleeper for PleaseEnableAFeatureOrProvideACustomSleeper {
    type Sleep = Ready<()>;
}

/// The default implementation of `Sleeper` uses `tokio::time::sleep`.
///
/// It will adhere to [pausing/auto-advancing](https://docs.rs/tokio/latest/tokio/time/fn.pause.html)
/// in Tokio's Runtime semantics, if enabled.
#[cfg(all(not(target_arch = "wasm32"), feature = "tokio-sleep"))]
#[derive(Clone, Copy, Debug, Default)]
pub struct TokioSleeper;

#[cfg(all(not(target_arch = "wasm32"), feature = "tokio-sleep"))]
impl Sleeper for TokioSleeper {
    type Sleep = tokio::time::Sleep;

    fn sleep(&self, dur: Duration) -> Self::Sleep {
        tokio::time::sleep(dur)
    }
}

/// The implementation of `Sleeper` that uses `futures_timer::Delay`.
///
/// This implementation is based on
/// the [`futures-timer`](https://docs.rs/futures-timer/latest/futures_timer/) crate.
/// It is async runtime agnostic and will also work in WASM environments.
#[cfg(feature = "futures-timer-sleep")]
#[derive(Clone, Copy, Debug, Default)]
pub struct FuturesTimerSleep;

#[cfg(feature = "futures-timer-sleep")]
impl Sleeper for FuturesTimerSleep {
    type Sleep = futures_timer::Delay;

    fn sleep(&self, dur: Duration) -> Self::Sleep {
        futures_timer::Delay::new(dur)
    }
}

/// The default implementation of `Sleeper` utilizes `gloo_timers::future::sleep`.
#[cfg(all(target_arch = "wasm32", feature = "gloo-timers-sleep"))]
#[derive(Clone, Copy, Debug, Default)]
pub struct GlooTimersSleep;

#[cfg(all(target_arch = "wasm32", feature = "gloo-timers-sleep"))]
impl Sleeper for GlooTimersSleep {
    type Sleep = gloo_timers::future::TimeoutFuture;

    fn sleep(&self, dur: Duration) -> Self::Sleep {
        gloo_timers::future::sleep(dur)
    }
}