use crate::dbs::node::Timestamp;
use crate::sql;
use sql::Duration;
use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering;
#[cfg(not(target_family = "wasm"))]
use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(target_family = "wasm")]
use wasmtimer::std::{SystemTime, UNIX_EPOCH};
#[allow(dead_code)]
#[derive(Clone)]
#[non_exhaustive]
pub enum SizedClock {
System(SystemClock),
#[cfg(test)]
Fake(FakeClock),
#[cfg(test)]
Inc(IncFakeClock),
}
impl SizedClock {
#[allow(dead_code)] pub(crate) fn system() -> Self {
Self::System(Default::default())
}
pub async fn now(&self) -> Timestamp {
match self {
SizedClock::System(c) => c.now(),
#[cfg(test)]
SizedClock::Fake(c) => c.now().await,
#[cfg(test)]
SizedClock::Inc(c) => c.now().await,
}
}
}
#[non_exhaustive]
pub struct FakeClock {
now: AtomicU64,
}
impl Clone for FakeClock {
fn clone(&self) -> Self {
FakeClock {
now: AtomicU64::new(self.now.load(Ordering::SeqCst)),
}
}
}
#[allow(dead_code)]
impl FakeClock {
pub fn new(now: Timestamp) -> Self {
FakeClock {
now: AtomicU64::new(now.value),
}
}
pub async fn now(&self) -> Timestamp {
Timestamp {
value: self.now.load(Ordering::SeqCst),
}
}
pub async fn set(&self, timestamp: Timestamp) {
self.now.store(timestamp.value, Ordering::SeqCst);
}
}
#[non_exhaustive]
pub struct IncFakeClock {
now: AtomicU64,
increment: Duration,
}
impl Clone for IncFakeClock {
fn clone(&self) -> Self {
IncFakeClock {
now: AtomicU64::new(self.now.load(Ordering::SeqCst)),
increment: self.increment,
}
}
}
#[allow(dead_code)]
impl IncFakeClock {
pub fn new(now: Timestamp, increment: Duration) -> Self {
IncFakeClock {
now: AtomicU64::new(now.value),
increment,
}
}
pub async fn now(&self) -> Timestamp {
self.now.fetch_add(self.increment.as_millis() as u64, Ordering::SeqCst);
Timestamp {
value: self.now.load(Ordering::SeqCst),
}
}
}
#[derive(Clone, Copy)]
#[non_exhaustive]
pub struct SystemClock;
impl SystemClock {
pub fn new() -> Self {
SystemClock
}
pub fn now(&self) -> Timestamp {
let now: u128 = match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(duration) => duration.as_millis(),
Err(error) => panic!("Clock may have gone backwards: {:?}", error.duration()),
};
Timestamp {
value: now as u64,
}
}
}
impl Default for SystemClock {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use crate::kvs::clock::SystemClock;
#[test]
fn get_clock_now() {
let clock = SystemClock::new();
let _ = clock.now();
}
}