cronback_lib/
shutdown.rs

1use tokio::sync::broadcast;
2/// The `Shutdown` struct listens for the signal and tracks that the signal has
3/// been received. Callers may query for whether the shutdown signal has been
4/// received or not.
5pub struct Shutdown {
6    /// `true` if the shutdown signal has been received
7    shutdown: bool,
8
9    notify: broadcast::Sender<()>,
10    /// The receive half of the channel used to listen for shutdown.
11    watch: broadcast::Receiver<()>,
12}
13
14impl Clone for Shutdown {
15    fn clone(&self) -> Self {
16        let notify = self.notify.clone();
17        let watch = notify.subscribe();
18        Self {
19            shutdown: self.shutdown,
20            notify,
21            watch,
22        }
23    }
24}
25
26impl Default for Shutdown {
27    fn default() -> Self {
28        let (notify, watch) = broadcast::channel(1);
29        Self {
30            shutdown: false,
31            notify,
32            watch,
33        }
34    }
35}
36
37impl Shutdown {
38    /// Create a new `Shutdown` backed by the given `broadcast::Receiver`.
39    pub fn new(notify: broadcast::Sender<()>) -> Shutdown {
40        let watch = notify.subscribe();
41        Shutdown {
42            shutdown: false,
43            notify,
44            watch,
45        }
46    }
47
48    /// Returns `true` if the shutdown signal has been received.
49    pub fn is_shutdown(&self) -> bool {
50        self.shutdown
51    }
52
53    /// Receive the shutdown notice, waiting if necessary.
54    pub async fn recv(&mut self) {
55        // If the shutdown signal has already been received, then return
56        // immediately.
57        if self.shutdown {
58            return;
59        }
60
61        // Cannot receive a "lag error" as only one value is ever sent.
62        let _ = self.watch.recv().await;
63
64        // Remember that the signal has been received.
65        self.shutdown = true;
66    }
67
68    pub fn broadcast_shutdown(&mut self) {
69        self.notify.send(()).unwrap();
70    }
71}