use super::traits::EngineClock;
pub struct LiveClock;
impl EngineClock for LiveClock {
fn now_ms(&self) -> i64 {
chrono::Utc::now().timestamp_millis()
}
}
pub struct HistoricalClock {
current_ms: std::sync::atomic::AtomicI64,
}
impl HistoricalClock {
pub fn new(initial_ms: i64) -> Self {
Self {
current_ms: std::sync::atomic::AtomicI64::new(initial_ms),
}
}
pub fn advance_to(&self, ms: i64) {
let prev = self.current_ms.load(std::sync::atomic::Ordering::Relaxed);
if ms < prev {
tracing::warn!(
prev_ms = prev,
new_ms = ms,
"HistoricalClock: backward time jump"
);
}
self.current_ms
.store(ms, std::sync::atomic::Ordering::Relaxed);
}
}
impl EngineClock for HistoricalClock {
fn now_ms(&self) -> i64 {
self.current_ms.load(std::sync::atomic::Ordering::Relaxed)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_live_clock_advances() {
let clock = LiveClock;
let t1 = clock.now_ms();
std::thread::sleep(std::time::Duration::from_millis(10));
let t2 = clock.now_ms();
assert!(t2 >= t1);
}
#[test]
fn test_historical_clock_returns_set_time() {
let clock = HistoricalClock::new(1_700_000_000_000);
assert_eq!(clock.now_ms(), 1_700_000_000_000);
clock.advance_to(1_700_000_001_000);
assert_eq!(clock.now_ms(), 1_700_000_001_000);
}
#[test]
fn test_historical_clock_backward_jump() {
let clock = HistoricalClock::new(1_700_000_001_000);
clock.advance_to(1_700_000_000_000);
assert_eq!(clock.now_ms(), 1_700_000_000_000);
}
}