Skip to main content

pingap_core/
util.rs

1// Copyright 2024-2025 Tree xie.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use coarsetime::{Clock, Updater};
16use ctor::ctor;
17use std::sync::LazyLock;
18
19static COARSE_CLOCK_UPDATER: LazyLock<Updater> = LazyLock::new(|| {
20    let interval = std::env::var("PINGAP_COARSE_CLOCK_INTERVAL")
21        .unwrap_or("10".to_string())
22        .parse::<u64>()
23        .unwrap_or(10)
24        .clamp(1, 500);
25    Updater::new(interval)
26        .start()
27        .expect("Failed to start coarse clock updater")
28});
29
30/// Initialize the time cache
31fn init_time_cache() {
32    LazyLock::force(&COARSE_CLOCK_UPDATER);
33}
34
35// 2022-05-07: 1651852800
36const SUPER_TIMESTAMP: u64 = 1651852800;
37
38/// Returns the number of seconds since the epoch
39#[inline]
40pub fn now_sec() -> u64 {
41    Clock::recent_since_epoch().as_secs()
42}
43
44/// Returns the number of seconds elapsed since SUPER_TIMESTAMP
45/// Returns 0 if the current time is before SUPER_TIMESTAMP
46#[inline]
47pub fn get_super_ts() -> u32 {
48    let super_ts_secs = SUPER_TIMESTAMP;
49    now_sec().saturating_sub(super_ts_secs) as u32
50}
51
52static HOST_NAME: LazyLock<String> = LazyLock::new(|| {
53    hostname::get()
54        .ok()
55        .as_deref()
56        .and_then(std::ffi::OsStr::to_str)
57        .unwrap_or("")
58        .to_string()
59});
60
61/// Returns the system hostname.
62///
63/// Returns:
64/// * `&'static str` - The system's hostname as a string slice
65pub fn get_hostname() -> &'static str {
66    HOST_NAME.as_str()
67}
68
69/// Returns the number of milliseconds since the epoch
70#[inline]
71pub fn now_ms() -> u64 {
72    Clock::recent_since_epoch().as_millis()
73}
74
75/// Returns the number of milliseconds since the epoch
76/// This is the real time, not the coarse time
77#[inline]
78pub fn real_now_ms() -> u64 {
79    Clock::now_since_epoch().as_millis()
80}
81
82#[ctor]
83fn init() {
84    init_time_cache();
85}
86
87#[cfg(test)]
88mod tests {
89    use super::{
90        get_hostname, get_super_ts, init_time_cache, now_ms, real_now_ms,
91    };
92    use pretty_assertions::assert_eq;
93
94    #[test]
95    fn test_super_ts() {
96        init_time_cache();
97        assert_eq!(true, get_super_ts() > 104017048);
98    }
99
100    #[test]
101    fn test_now_ms() {
102        init_time_cache();
103        assert_eq!(true, now_ms() > 1755870295813);
104    }
105
106    #[test]
107    fn test_real_now_ms() {
108        init_time_cache();
109        assert_eq!(true, real_now_ms() > 1755870295813);
110    }
111
112    #[test]
113    fn test_get_hostname() {
114        assert_eq!(false, get_hostname().is_empty());
115    }
116}