diff options
author | Vika <vika@fireburn.ru> | 2024-11-13 06:41:45 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2024-11-13 06:41:45 +0300 |
commit | 42506c91065cd69bd03ce68715662dd898e2181f (patch) | |
tree | b22dca97eedcd15ec957cd18f36c62a865397115 /tower-watchdog/src/watchdog.rs | |
parent | 3d40cca255d462cc190a602f7fb16c1f4ade821d (diff) | |
download | kittybox-42506c91065cd69bd03ce68715662dd898e2181f.tar.zst |
tower-watchdog: init at 1.0.0
Wait, is this my first self-contained crate? Not bad. I like this. Maybe I'll go publish it to crates.io? Change-Id: I340d0839746ff1cfbcc4c82c230ae2adff2a92f7
Diffstat (limited to 'tower-watchdog/src/watchdog.rs')
-rw-r--r-- | tower-watchdog/src/watchdog.rs | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/tower-watchdog/src/watchdog.rs b/tower-watchdog/src/watchdog.rs new file mode 100644 index 0000000..4162294 --- /dev/null +++ b/tower-watchdog/src/watchdog.rs @@ -0,0 +1,45 @@ +/// A watchdog timer with a timeout that needs to be regularly pinged +/// to prevent it from firing. +/// +/// **Note**: the behavior of the watchdog is undefined (but will not +/// result in a crash or put the watchdog in an invalid state) if it +/// is pet at the last possible moment, for example, like this: +/// +/// ```no_compile +/// let (watchdog, pet) = /* ... */ +/// tokio::select! { +/// tokio::time::sleep(watchdog.timeout).then(move |()| pet.pet()) = _ => { eprintln!("foo"); }, +/// watchdog.wait() = _ => { eprintln!("bar"); } +/// ``` +pub struct Watchdog { + rx: tokio::sync::mpsc::Receiver<()>, + /// Timeout of this watchdog. + pub timeout: std::time::Duration, +} +#[derive(Clone)] +pub(crate) struct Pet(tokio::sync::mpsc::Sender<()>); + +pub(crate) fn watchdog(timeout: std::time::Duration) -> (Watchdog, Pet) { + let (tx, rx) = tokio::sync::mpsc::channel::<()>(1); + let pet = Pet(tx); + let watchdog = Watchdog { rx, timeout }; + + (watchdog, pet) +} + +impl Watchdog { + /// Wait until the watchdog fires from not being pet in a while. + /// + /// The watchdog doesn't start waiting for pets and scritches + /// until you await the future returned from this method. + pub async fn wait(mut self) { + while let Ok(Some(())) = tokio::time::timeout(self.timeout, self.rx.recv()).await {} + } +} + +impl Pet { + pub(crate) async fn pet_owned(self) -> Result<(), tokio::sync::mpsc::error::SendError<()>> { + let tx = self.0.clone(); + tx.send(()).await + } +} |