Skip to main content

vorma_tasks/
clock.rs

1use std::time::{Duration, Instant};
2
3/// Monotonic timestamp used for cross-execution-context cache expiry.
4#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
5pub struct ClockInstant {
6	nanos_since_origin: u128,
7}
8
9impl ClockInstant {
10	/// Create a timestamp from a duration since an arbitrary monotonic origin.
11	pub fn from_duration_since_origin(duration: Duration) -> Self {
12		Self {
13			nanos_since_origin: duration.as_nanos(),
14		}
15	}
16
17	pub(crate) fn saturating_add_duration(self, duration: Duration) -> Self {
18		Self {
19			nanos_since_origin: self.nanos_since_origin.saturating_add(duration.as_nanos()),
20		}
21	}
22
23	pub(crate) fn saturating_duration_since(self, earlier: Self) -> Duration {
24		let nanos = self
25			.nanos_since_origin
26			.saturating_sub(earlier.nanos_since_origin);
27		Duration::from_nanos(nanos.min(u64::MAX.into()) as u64)
28	}
29}
30
31/// Monotonic clock used by [`crate::Tasks`] for TTL expiry.
32pub trait Clock: Send + Sync + 'static {
33	/// Return the current monotonic timestamp.
34	fn now(&self) -> ClockInstant;
35}
36
37/// Native monotonic clock backed by [`std::time::Instant`].
38#[derive(Clone, Debug)]
39pub struct SystemClock {
40	origin: Instant,
41}
42
43impl SystemClock {
44	/// Create a system monotonic clock with a fresh origin.
45	pub fn new() -> Self {
46		Self {
47			origin: Instant::now(),
48		}
49	}
50}
51
52impl Default for SystemClock {
53	fn default() -> Self {
54		Self::new()
55	}
56}
57
58impl Clock for SystemClock {
59	fn now(&self) -> ClockInstant {
60		ClockInstant::from_duration_since_origin(self.origin.elapsed())
61	}
62}