1use std::time::Duration;
12use tokio::sync::watch;
13
14#[derive(Clone)]
16pub struct Shutdown {
17 rx: watch::Receiver<bool>,
18}
19
20impl Shutdown {
21 pub(crate) fn new(rx: watch::Receiver<bool>) -> Self {
22 Self { rx }
23 }
24
25 pub fn never() -> Self {
27 let (tx, rx) = watch::channel(false);
28 std::mem::forget(tx);
30 Self { rx }
31 }
32
33 pub fn is_triggered(&self) -> bool {
35 *self.rx.borrow()
36 }
37
38 pub async fn wait(&self) {
40 let mut rx = self.rx.clone();
41 loop {
42 if *rx.borrow_and_update() {
43 return;
44 }
45 if rx.changed().await.is_err() {
46 return;
48 }
49 }
50 }
51
52 pub async fn sleep(&self, duration: Duration) -> bool {
56 tokio::select! {
57 _ = tokio::time::sleep(duration) => !self.is_triggered(),
58 _ = self.wait() => false,
59 }
60 }
61}
62
63#[derive(Clone)]
66pub struct Context {
67 pub(crate) state: std::sync::Arc<crate::request::StateMap>,
68 shutdown: Shutdown,
69}
70
71impl Context {
72 pub(crate) fn new(state: std::sync::Arc<crate::request::StateMap>, shutdown: Shutdown) -> Self {
73 Self { state, shutdown }
74 }
75
76 pub fn state<T: Send + Sync + 'static>(&self) -> crate::error::Result<&T> {
78 self.state.get::<T>().ok_or_else(|| {
79 crate::error::Error::internal(format!(
80 "State of type {} is not registered",
81 std::any::type_name::<T>()
82 ))
83 })
84 }
85
86 pub fn shutdown(&self) -> Shutdown {
88 self.shutdown.clone()
89 }
90
91 pub async fn sleep(&self, duration: Duration) -> bool {
93 self.shutdown.sleep(duration).await
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[tokio::test]
102 async fn wait_sleep_and_trigger() {
103 let (tx, rx) = watch::channel(false);
104 let s = Shutdown::new(rx);
105 assert!(!s.is_triggered());
106 assert!(s.sleep(Duration::from_millis(5)).await);
107
108 let s2 = s.clone();
109 let waiter = tokio::spawn(async move { s2.wait().await });
110 tx.send(true).unwrap();
111 waiter.await.unwrap();
112 assert!(s.is_triggered());
113 s.wait().await;
115 assert!(!s.sleep(Duration::from_secs(60)).await);
116 }
117
118 #[tokio::test]
119 async fn sleep_is_interrupted_by_the_signal() {
120 let (tx, rx) = watch::channel(false);
121 let s = Shutdown::new(rx);
122 let sleeper = tokio::spawn({
123 let s = s.clone();
124 async move { s.sleep(Duration::from_secs(60)).await }
125 });
126 tokio::time::sleep(Duration::from_millis(20)).await;
127 tx.send(true).unwrap();
128 assert!(!tokio::time::timeout(Duration::from_secs(5), sleeper)
129 .await
130 .unwrap()
131 .unwrap());
132 }
133
134 #[tokio::test]
135 async fn never_does_not_fire() {
136 let s = Shutdown::never();
137 assert!(!s.is_triggered());
138 assert!(tokio::time::timeout(Duration::from_millis(30), s.wait())
139 .await
140 .is_err());
141 }
142}