sentinel_core/utils/
time.rs

1//! Timer implementation for the Sentinel.
2//! It supports a cached timer and a real-time timer from `unix_timestamp_nanos`.
3
4use lazy_static::lazy_static;
5use time::{macros::format_description, Duration, OffsetDateTime};
6
7lazy_static! {
8    static ref UNIX_TIME_UNIT_OFFSET: i128 = (Duration::MILLISECOND / Duration::NANOSECOND) as i128;
9}
10
11#[inline]
12pub fn unix_time_unit_offset() -> u64 {
13    *UNIX_TIME_UNIT_OFFSET as u64
14}
15
16#[inline]
17pub fn sleep_for_ms(ms: u64) {
18    std::thread::sleep(std::time::Duration::from_millis(ms));
19}
20
21#[inline]
22pub fn sleep_for_ns(ns: u64) {
23    std::thread::sleep(std::time::Duration::from_nanos(ns));
24}
25
26#[inline]
27fn cal_curr_time_millis() -> u64 {
28    (OffsetDateTime::now_utc().unix_timestamp_nanos() / (*UNIX_TIME_UNIT_OFFSET)) as u64
29}
30
31#[inline]
32pub fn format_time_millis(ts_millis: u64) -> String {
33    OffsetDateTime::from_unix_timestamp_nanos(milli2nano(ts_millis))
34        .unwrap()
35        .format(format_description!("[hour]:[minute]:[second]"))
36        .unwrap()
37}
38
39#[inline]
40/// The format is corresponding to `crate::log::metric::METRIC_FILE_PATTERN`
41pub fn format_date(ts_millis: u64) -> String {
42    OffsetDateTime::from_unix_timestamp_nanos(milli2nano(ts_millis))
43        .unwrap()
44        .format(format_description!("[year]-[month]-[day]"))
45        .unwrap()
46}
47
48#[inline]
49pub fn format_time_nanos_curr() -> String {
50    OffsetDateTime::from_unix_timestamp_nanos(curr_time_nanos())
51        .unwrap()
52        .format(format_description!("[hour]:[minute]:[second]"))
53        .unwrap()
54}
55
56pub fn curr_time_millis() -> u64 {
57    // todo: conditional compilation, `config::use_cache_time()`
58    let ticker_time = curr_time_millis_with_ticker();
59    if ticker_time > 0 {
60        ticker_time
61    } else {
62        cal_curr_time_millis()
63    }
64}
65
66#[inline]
67pub fn curr_time_nanos() -> i128 {
68    OffsetDateTime::now_utc().unix_timestamp_nanos()
69}
70
71#[inline]
72pub fn milli2nano<T: Into<i128>>(t: T) -> i128 {
73    *UNIX_TIME_UNIT_OFFSET * t.into()
74}
75
76pub use ticker::*;
77
78// provide cached time by a ticker
79pub mod ticker {
80    use super::*;
81    use lazy_static::lazy_static;
82    use std::sync::atomic::{AtomicU64, Ordering};
83
84    lazy_static! {
85        static ref NOW_IN_MS: AtomicU64 = AtomicU64::new(0);
86    }
87
88    /// `start_time_ticker()` starts a background task that caches current timestamp per millisecond,
89    /// which may provide better performance in high-concurrency scenarios.
90    pub fn start_time_ticker() {
91        update_time();
92        std::thread::spawn(move || loop {
93            update_time();
94            std::thread::sleep(std::time::Duration::from_millis(1));
95        });
96    }
97    #[inline]
98    fn update_time() {
99        let curr = cal_curr_time_millis();
100        NOW_IN_MS.store(curr, Ordering::SeqCst);
101    }
102
103    #[inline]
104    pub(super) fn curr_time_millis_with_ticker() -> u64 {
105        NOW_IN_MS.load(Ordering::SeqCst)
106    }
107}