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}