Skip to main content

execution_policy/
attempt.rs

1//! Per-attempt metadata handed to operation closures.
2
3use std::marker::PhantomData;
4use std::time::{Duration, Instant};
5
6/// Metadata for the current attempt. `number()` is 1-based.
7#[non_exhaustive]
8#[derive(Debug, Clone, Copy)]
9pub struct Attempt<'a> {
10    number: u32,
11    start: Instant,
12    now: Instant,
13    _borrow: PhantomData<&'a ()>,
14}
15
16impl<'a> Attempt<'a> {
17    pub(crate) fn new(number: u32, start: Instant, now: Instant) -> Self {
18        Self {
19            number,
20            start,
21            now,
22            _borrow: PhantomData,
23        }
24    }
25
26    /// 1-based attempt index (first attempt returns 1).
27    pub fn number(&self) -> u32 {
28        self.number
29    }
30
31    /// Time elapsed since the first attempt began.
32    pub fn elapsed(&self) -> Duration {
33        self.now.duration_since(self.start)
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    #[test]
42    fn number_is_one_based() {
43        let t = Instant::now();
44        let a = Attempt::new(1, t, t);
45        assert_eq!(a.number(), 1);
46    }
47
48    #[test]
49    fn elapsed_reflects_clock() {
50        let start = Instant::now();
51        let now = start + Duration::from_millis(250);
52        let a = Attempt::new(2, start, now);
53        assert_eq!(a.elapsed(), Duration::from_millis(250));
54    }
55}