mirror of https://github.com/chipsenkbeil/distant
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.0 KiB
Rust
99 lines
3.0 KiB
Rust
use std::time::Duration;
|
|
|
|
use log::*;
|
|
use tokio::sync::watch;
|
|
|
|
use super::Shutdown;
|
|
use crate::common::utils::Timer;
|
|
|
|
/// Cloneable notification for when a [`ShutdownTimer`] has completed.
|
|
#[derive(Clone)]
|
|
pub(crate) struct ShutdownNotification(watch::Receiver<()>);
|
|
|
|
impl ShutdownNotification {
|
|
/// Waits to receive a notification that the shutdown timer has concluded
|
|
pub async fn wait(&mut self) {
|
|
let _ = self.0.changed().await;
|
|
}
|
|
}
|
|
|
|
/// Wrapper around [`Timer`] to support shutdown-specific notifications.
|
|
pub(crate) struct ShutdownTimer {
|
|
timer: Timer<()>,
|
|
watcher: ShutdownNotification,
|
|
shutdown: Shutdown,
|
|
}
|
|
|
|
impl ShutdownTimer {
|
|
// Creates and starts the timer that will be used shutdown the server after duration elapsed.
|
|
pub fn start(shutdown: Shutdown) -> Self {
|
|
let (tx, rx) = watch::channel(());
|
|
let mut timer = match shutdown {
|
|
// Create a timer that will complete after `duration`, dropping it to ensure that it
|
|
// will always happen no matter if stop/abort is called
|
|
Shutdown::After(duration) => {
|
|
info!(
|
|
"Server shutdown timer configured: terminate after {}s",
|
|
duration.as_secs_f32()
|
|
);
|
|
Timer::new(duration, async move {
|
|
let _ = tx.send(());
|
|
})
|
|
}
|
|
|
|
// Create a timer that will complete after `duration`
|
|
Shutdown::Lonely(duration) => {
|
|
info!(
|
|
"Server shutdown timer configured: terminate after no activity for {}s",
|
|
duration.as_secs_f32()
|
|
);
|
|
Timer::new(duration, async move {
|
|
let _ = tx.send(());
|
|
})
|
|
}
|
|
|
|
// Create a timer that will never complete (max timeout possible) so we hold on to the
|
|
// sender to avoid the receiver from completing
|
|
Shutdown::Never => {
|
|
info!("Server shutdown timer configured: never terminate");
|
|
Timer::new(Duration::MAX, async move {
|
|
let _ = tx.send(());
|
|
})
|
|
}
|
|
};
|
|
|
|
timer.start();
|
|
|
|
Self {
|
|
timer,
|
|
watcher: ShutdownNotification(rx),
|
|
shutdown,
|
|
}
|
|
}
|
|
|
|
/// Restarts the timer, doing nothing if the timer is already running
|
|
pub fn restart(&mut self) {
|
|
if !self.timer.is_running() {
|
|
self.timer.start();
|
|
}
|
|
}
|
|
|
|
/// Stops the timer, only applying if the timer is `lonely`
|
|
pub fn stop(&self) {
|
|
if let Shutdown::Lonely(_) = self.shutdown {
|
|
self.timer.stop();
|
|
}
|
|
}
|
|
|
|
/// Stops the timer completely by killing the internal callback task, meaning it can never be
|
|
/// started again
|
|
pub fn abort(&self) {
|
|
self.timer.abort();
|
|
}
|
|
|
|
/// Clones the notification
|
|
pub fn clone_notification(&self) -> ShutdownNotification {
|
|
self.watcher.clone()
|
|
}
|
|
}
|