1use std::time::Duration;
12use tokio::sync::watch;
13
14#[derive(Clone)]
16pub struct Shutdown {
17 rx: watch::Receiver<bool>,
18 drain: watch::Receiver<bool>,
19}
20
21impl Shutdown {
22 pub(crate) fn new(rx: watch::Receiver<bool>) -> Self {
23 let (tx, drain) = watch::channel(false);
25 std::mem::forget(tx);
26 Self { rx, drain }
27 }
28
29 pub(crate) fn with_drain(rx: watch::Receiver<bool>, drain: watch::Receiver<bool>) -> Self {
30 Self { rx, drain }
31 }
32
33 pub fn never() -> Self {
35 let (tx, rx) = watch::channel(false);
36 std::mem::forget(tx);
38 Self::new(rx)
39 }
40
41 pub fn is_draining(&self) -> bool {
46 *self.drain.borrow() || self.is_triggered()
47 }
48
49 pub fn is_triggered(&self) -> bool {
51 *self.rx.borrow()
52 }
53
54 pub async fn wait(&self) {
56 let mut rx = self.rx.clone();
57 loop {
58 if *rx.borrow_and_update() {
59 return;
60 }
61 if rx.changed().await.is_err() {
62 return;
64 }
65 }
66 }
67
68 pub async fn sleep(&self, duration: Duration) -> bool {
72 tokio::select! {
73 _ = tokio::time::sleep(duration) => !self.is_triggered(),
74 _ = self.wait() => false,
75 }
76 }
77}
78
79#[derive(Clone)]
82pub struct Context {
83 pub(crate) state: std::sync::Arc<crate::request::StateMap>,
84 shutdown: Shutdown,
85}
86
87impl Context {
88 pub(crate) fn new(state: std::sync::Arc<crate::request::StateMap>, shutdown: Shutdown) -> Self {
89 Self { state, shutdown }
90 }
91
92 pub fn state<T: Send + Sync + 'static>(&self) -> crate::error::Result<&T> {
94 self.state.get::<T>().ok_or_else(|| {
95 crate::error::Error::internal(format!(
96 "State of type {} is not registered",
97 std::any::type_name::<T>()
98 ))
99 })
100 }
101
102 pub fn shutdown(&self) -> Shutdown {
104 self.shutdown.clone()
105 }
106
107 pub async fn sleep(&self, duration: Duration) -> bool {
109 self.shutdown.sleep(duration).await
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[tokio::test]
118 async fn wait_sleep_and_trigger() {
119 let (tx, rx) = watch::channel(false);
120 let s = Shutdown::new(rx);
121 assert!(!s.is_triggered());
122 assert!(s.sleep(Duration::from_millis(5)).await);
123
124 let s2 = s.clone();
125 let waiter = tokio::spawn(async move { s2.wait().await });
126 tx.send(true).unwrap();
127 waiter.await.unwrap();
128 assert!(s.is_triggered());
129 s.wait().await;
131 assert!(!s.sleep(Duration::from_secs(60)).await);
132 }
133
134 #[tokio::test]
135 async fn sleep_is_interrupted_by_the_signal() {
136 let (tx, rx) = watch::channel(false);
137 let s = Shutdown::new(rx);
138 let sleeper = tokio::spawn({
139 let s = s.clone();
140 async move { s.sleep(Duration::from_secs(60)).await }
141 });
142 tokio::time::sleep(Duration::from_millis(20)).await;
143 tx.send(true).unwrap();
144 assert!(!tokio::time::timeout(Duration::from_secs(5), sleeper)
145 .await
146 .unwrap()
147 .unwrap());
148 }
149
150 #[test]
151 fn draining_precedes_or_equals_shutdown() {
152 let (tx, rx) = watch::channel(false);
153 let (dtx, drx) = watch::channel(false);
154 let s = Shutdown::with_drain(rx, drx);
155 assert!(!s.is_draining());
156 dtx.send(true).unwrap();
157 assert!(s.is_draining() && !s.is_triggered());
158 tx.send(true).unwrap();
159 assert!(s.is_triggered());
160
161 let (tx, rx) = watch::channel(false);
163 let s = Shutdown::new(rx);
164 assert!(!s.is_draining());
165 tx.send(true).unwrap();
166 assert!(s.is_draining());
167 }
168
169 #[tokio::test]
170 async fn never_does_not_fire() {
171 let s = Shutdown::never();
172 assert!(!s.is_triggered());
173 assert!(tokio::time::timeout(Duration::from_millis(30), s.wait())
174 .await
175 .is_err());
176 }
177}