Skip to main content

atomr_remote/
deadline_detector.rs

1//! Deadline failure detector.
2//!
3//! A simpler FD: any peer that hasn't heartbeat within `acceptable_heartbeat_pause`
4//! is considered unreachable.
5
6use std::time::{Duration, Instant};
7
8use parking_lot::Mutex;
9
10use crate::failure_detector::FailureDetector;
11
12pub struct DeadlineFailureDetector {
13    pause: Duration,
14    last_heartbeat: Mutex<Option<Instant>>,
15}
16
17impl DeadlineFailureDetector {
18    pub fn new(acceptable_heartbeat_pause: Duration) -> Self {
19        Self { pause: acceptable_heartbeat_pause, last_heartbeat: Mutex::new(None) }
20    }
21}
22
23impl FailureDetector for DeadlineFailureDetector {
24    fn is_available(&self) -> bool {
25        match *self.last_heartbeat.lock() {
26            None => true,
27            Some(t) => t.elapsed() < self.pause,
28        }
29    }
30
31    fn is_monitoring(&self) -> bool {
32        self.last_heartbeat.lock().is_some()
33    }
34
35    fn heartbeat(&self) {
36        *self.last_heartbeat.lock() = Some(Instant::now());
37    }
38
39    fn reset(&self) {
40        *self.last_heartbeat.lock() = None;
41    }
42
43    fn since_last_heartbeat(&self) -> Option<Duration> {
44        self.last_heartbeat.lock().map(|t| t.elapsed())
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn unavailable_after_pause() {
54        let d = DeadlineFailureDetector::new(Duration::from_millis(20));
55        d.heartbeat();
56        assert!(d.is_available());
57        std::thread::sleep(Duration::from_millis(30));
58        assert!(!d.is_available());
59    }
60}