Skip to main content

reifydb_runtime/context/clock/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4#[cfg(any(reifydb_target = "host", reifydb_dst))]
5mod host;
6#[cfg(reifydb_target = "wasi")]
7mod wasi;
8#[cfg(reifydb_target = "wasm")]
9mod wasm;
10
11#[cfg(any(reifydb_target = "host", reifydb_dst))]
12pub use host::{Clock, Instant, MockClock};
13use reifydb_value::{clock::ClockNow, value::datetime::DateTime};
14#[cfg(reifydb_target = "wasi")]
15pub use wasi::{Clock, Instant, MockClock};
16#[cfg(reifydb_target = "wasm")]
17pub use wasm::{Clock, Instant, MockClock};
18
19impl ClockNow for Clock {
20	fn now(&self) -> DateTime {
21		Clock::now(self)
22	}
23}
24
25pub trait TimerWake: Send + Sync {
26	fn wake(&self);
27}
28
29#[derive(Clone, Copy, PartialEq, Eq, Debug)]
30pub struct TimerId(u64);
31
32#[cfg(test)]
33mod tests {
34	#[cfg(all(reifydb_target = "host", not(reifydb_dst)))]
35	use std::thread;
36
37	use super::*;
38
39	#[test]
40	fn test_real_clock() {
41		let clock = Clock::Real;
42		let t1 = clock.now().to_millis();
43		// Busy work rather than a sleep; the assertion only requires the clock not to go
44		// backwards, so it holds whether or not a millisecond actually elapsed.
45		let mut sum = 0;
46		for i in 0..10000 {
47			sum += i;
48		}
49		let t2 = clock.now().to_millis();
50		assert!(t2 >= t1, "Time should not go backwards");
51		let _ = sum;
52	}
53
54	#[test]
55	fn test_mock_clock_initial() {
56		let mock = MockClock::from_millis(1000);
57		let clock = Clock::Mock(mock);
58
59		assert_eq!(clock.now().to_millis(), 1000);
60		assert_eq!(clock.now().to_micros(), 1_000_000);
61		assert_eq!(clock.now().to_nanos(), 1_000_000_000);
62	}
63
64	#[test]
65	fn test_mock_clock_set() {
66		let mock = MockClock::from_millis(0);
67		mock.set_millis(5000);
68
69		assert_eq!(mock.now().to_millis(), 5000);
70
71		mock.set_micros(6_000_000);
72		assert_eq!(mock.now().to_millis(), 6000);
73	}
74
75	#[test]
76	fn test_mock_clock_advance() {
77		let mock = MockClock::from_millis(1000);
78		let clock = Clock::Mock(mock.clone());
79
80		assert_eq!(clock.now().to_millis(), 1000);
81
82		mock.advance_millis(500);
83		assert_eq!(clock.now().to_millis(), 1500);
84
85		mock.advance_micros(500_000);
86		assert_eq!(clock.now().to_millis(), 2000);
87
88		mock.advance_nanos(500_000_000);
89		assert_eq!(clock.now().to_millis(), 2500);
90	}
91
92	#[cfg(all(reifydb_target = "host", not(reifydb_dst)))]
93	#[test]
94	fn test_mock_clock_thread_safe() {
95		let mock = MockClock::from_millis(1000);
96		let mock_clone = mock.clone();
97
98		let handle = thread::spawn(move || {
99			mock_clone.advance_millis(500);
100			mock_clone.now().to_millis()
101		});
102
103		let result = handle.join().unwrap();
104		assert_eq!(result, 1500);
105		assert_eq!(mock.now().to_millis(), 1500);
106	}
107
108	#[test]
109	fn test_nanosecond_precision() {
110		let mock = MockClock::new(1_234_567_890_123_456_789);
111		let clock = Clock::Mock(mock);
112
113		assert_eq!(clock.now().to_nanos(), 1_234_567_890_123_456_789);
114		assert_eq!(clock.now().to_micros(), 1_234_567_890_123_456);
115		assert_eq!(clock.now().to_millis(), 1_234_567_890_123);
116		assert_eq!(clock.now().to_epoch_secs(), 1_234_567_890);
117	}
118}