1use crate::err::Error;
2use crate::err::Error::TimestampOverflow;
3use crate::sql::Duration;
4use derive::{Key, Store};
5use revision::revisioned;
6use serde::{Deserialize, Serialize};
7use std::ops::{Add, Sub};
8
9#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize, PartialOrd, Hash, Store)]
12#[revisioned(revision = 1)]
13pub struct ClusterMembership {
14 pub name: String,
15 pub heartbeat: Timestamp,
18}
19#[derive(
23 Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize, PartialOrd, Hash, Store, Default,
24)]
25#[revisioned(revision = 1)]
26pub struct Timestamp {
27 pub value: u64,
28}
29
30impl From<u64> for Timestamp {
31 fn from(ts: u64) -> Self {
32 Timestamp {
33 value: ts,
34 }
35 }
36}
37
38#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize, PartialOrd, Hash, Key)]
41#[revisioned(revision = 1)]
42pub struct KeyTimestamp {
43 pub value: u64,
44}
45
46impl From<&Timestamp> for KeyTimestamp {
47 fn from(ts: &Timestamp) -> Self {
48 KeyTimestamp {
49 value: ts.value,
50 }
51 }
52}
53
54impl Add<&Duration> for &Timestamp {
55 type Output = Timestamp;
56 fn add(self, rhs: &Duration) -> Timestamp {
57 Timestamp {
58 value: self.value + rhs.as_millis() as u64,
59 }
60 }
61}
62
63impl Sub<&Duration> for &Timestamp {
64 type Output = Result<Timestamp, Error>;
65 fn sub(self, rhs: &Duration) -> Self::Output {
66 let millis = rhs.as_millis() as u64;
67 if self.value <= millis {
68 return Err(TimestampOverflow(format!(
70 "Failed to subtract {} from {}",
71 &millis, &self.value
72 )));
73 }
74 Ok(Timestamp {
75 value: self.value - millis,
76 })
77 }
78}
79
80#[cfg(test)]
81mod test {
82 use crate::dbs::node::Timestamp;
83 use crate::sql::Duration;
84 use chrono::prelude::Utc;
85 use chrono::TimeZone;
86
87 #[test]
88 fn timestamps_can_be_added_duration() {
89 let t = Utc.with_ymd_and_hms(2000, 1, 1, 12, 30, 0).unwrap();
90 let ts = Timestamp {
91 value: t.timestamp_millis() as u64,
92 };
93
94 let hour = Duration(core::time::Duration::from_secs(60 * 60));
95 let ts = &ts + &hour;
96 let ts = &ts + &hour;
97 let ts = &ts + &hour;
98
99 let end_time = Utc.timestamp_millis_opt(ts.value as i64).unwrap();
100 let expected_end_time = Utc.with_ymd_and_hms(2000, 1, 1, 15, 30, 0).unwrap();
101 assert_eq!(end_time, expected_end_time);
102 }
103
104 #[test]
105 fn timestamps_can_be_subtracted_duration() {
106 let t = Utc.with_ymd_and_hms(2000, 1, 1, 12, 30, 0).unwrap();
107 let ts = Timestamp {
108 value: t.timestamp_millis() as u64,
109 };
110
111 let hour = Duration(core::time::Duration::from_secs(60 * 60));
112 let ts = (&ts - &hour).unwrap();
113 let ts = (&ts - &hour).unwrap();
114 let ts = (&ts - &hour).unwrap();
115
116 let end_time = Utc.timestamp_millis_opt(ts.value as i64).unwrap();
117 let expected_end_time = Utc.with_ymd_and_hms(2000, 1, 1, 9, 30, 0).unwrap();
118 assert_eq!(end_time, expected_end_time);
119 }
120}