execution_policy/core/mod.rs
1//! Runtime abstraction: clock, sleeping, and RNG behind one object-safe trait.
2
3use std::future::Future;
4use std::pin::Pin;
5use std::time::{Duration, Instant};
6
7#[cfg(any(feature = "tokio", feature = "test-util"))]
8pub(crate) mod rng;
9
10#[cfg(feature = "tokio")]
11mod tokio;
12#[cfg(feature = "tokio")]
13pub use tokio::TokioCore;
14
15#[cfg(feature = "test-util")]
16mod test;
17#[cfg(feature = "test-util")]
18pub use test::{ManualClock, TestCore};
19
20/// A boxed future. [`Core::sleep`] returns this so the trait stays object-safe
21/// (`Arc<dyn Core>` works); the box is on the cold backoff path only.
22///
23/// `+ Send` so the engine future (and therefore `ExecutionPolicy::run`/`execute`)
24/// is `Send` and can be `.await`ed inside `async-trait` `Send` futures and
25/// `tokio::spawn`. Both cores already produce `Send` sleeps (Tokio's `Sleep` is
26/// `Send`; `TestCore`'s `ManualSleep` is `Arc<Mutex<…>>`-backed).
27pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
28
29/// The policy engine's access to time, sleeping, and randomness.
30///
31/// Object-safe by construction. Implementors: [`TokioCore`] (default) and
32/// [`TestCore`] (deterministic, for tests).
33pub trait Core {
34 /// Current monotonic instant.
35 fn now(&self) -> Instant;
36 /// A future that completes after `dur` of this `Core`'s time.
37 fn sleep(&self, dur: Duration) -> BoxFuture<'_, ()>;
38 /// Next pseudo-random `u64` (used for jitter). Not cryptographic.
39 fn next_u64(&self) -> u64;
40}
41
42/// The `Core` used by `ExecutionPolicy::builder().build()`.
43#[cfg(feature = "tokio")]
44pub type DefaultCore = TokioCore;