Skip to main content

ag_store/
timestamp.rs

1//! Timestamp boundary for persistence writes.
2
3use std::sync::Arc;
4use std::time::{SystemTime, UNIX_EPOCH};
5
6/// Supplies Unix timestamps for rows written by persistence adapters.
7pub trait TimestampSource: Send + Sync {
8    /// Returns the current Unix timestamp in whole seconds.
9    fn now_timestamp_seconds(&self) -> i64;
10}
11
12impl<TimestampFn> TimestampSource for TimestampFn
13where
14    TimestampFn: Fn() -> i64 + Send + Sync,
15{
16    fn now_timestamp_seconds(&self) -> i64 {
17        self()
18    }
19}
20
21/// Returns a timestamp source backed by the host system clock.
22pub(crate) fn system_timestamp_source() -> Arc<dyn TimestampSource> {
23    Arc::new(system_timestamp_seconds)
24}
25
26/// Converts the host system clock to a Unix timestamp in whole seconds.
27fn system_timestamp_seconds() -> i64 {
28    SystemTime::now()
29        .duration_since(UNIX_EPOCH)
30        .ok()
31        .and_then(|duration| i64::try_from(duration.as_secs()).ok())
32        .unwrap_or_default()
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38
39    #[test]
40    fn closure_timestamp_source_returns_injected_value() {
41        // Arrange
42        let timestamp_source = || 123;
43
44        // Act
45        let timestamp = timestamp_source.now_timestamp_seconds();
46
47        // Assert
48        assert_eq!(timestamp, 123);
49    }
50
51    #[test]
52    fn system_timestamp_source_returns_a_post_epoch_value() {
53        // Arrange
54        let timestamp_source = system_timestamp_source();
55
56        // Act
57        let timestamp = timestamp_source.now_timestamp_seconds();
58
59        // Assert
60        assert!(timestamp > 0);
61    }
62}