use std::future::Future;
use std::pin::pin;
use std::time::Duration;
use super::execute_or_shutdown;
use crate::MakeDelay;
use crate::Spawn;
use crate::debug;
use crate::info;
pub trait NotifyAction: Send + 'static {
fn name(&self) -> &str;
fn run(&mut self) -> impl Future<Output = ()> + Send;
fn notified(&mut self) -> impl Future<Output = ()> + Send;
}
pub trait NotifyActionExt: NotifyAction {
fn schedule_by_notify<Fut, S, D>(
mut self,
is_shutdown: Fut,
spawn: &S,
make_delay: D,
initial_delay: Option<Duration>,
) where
Self: Sized,
Fut: Future<Output = ()> + Send + 'static,
S: Spawn,
D: MakeDelay + Send + 'static,
{
spawn.spawn(async move {
info!(
"start scheduled task {} with initial delay {:?}",
self.name(),
initial_delay
);
let mut is_shutdown = pin!(is_shutdown);
'schedule: {
if let Some(initial_delay) = initial_delay {
if initial_delay > Duration::ZERO
&& execute_or_shutdown(make_delay.delay(initial_delay), &mut is_shutdown)
.await
.is_break()
{
break 'schedule;
}
}
loop {
debug!("executing scheduled task {}", self.name());
if execute_or_shutdown(self.run(), &mut is_shutdown)
.await
.is_break()
{
break;
};
if execute_or_shutdown(self.notified(), &mut is_shutdown)
.await
.is_break()
{
break;
}
}
}
info!("scheduled task {} is shutdown", self.name());
});
}
}
impl<T: NotifyAction> NotifyActionExt for T {}