use ockam_core::async_trait;
use std::sync::Arc;
use tokio::runtime::Handle;
use tokio::sync::mpsc;
use tokio::sync::mpsc::{Receiver, Sender};
use tokio::time::{timeout, Duration};
#[async_trait]
pub(crate) trait ScheduledTask: Send + Sync + 'static {
async fn run(&self);
}
#[derive(Clone)]
pub(crate) struct Scheduler {
task: Arc<dyn ScheduledTask>,
interval: Duration,
tx: Sender<()>,
}
impl Scheduler {
pub(crate) fn create(
task: Arc<dyn ScheduledTask>,
interval: Duration,
runtime: &Handle,
) -> Self {
let (tx, rx) = mpsc::channel::<()>(1);
let instance = Self { tx, task, interval };
{
let instance = instance.clone();
runtime.spawn(async move {
instance.start(rx).await;
});
}
instance
}
pub(crate) fn schedule_now(&self) {
let _ = self.tx.try_send(());
}
async fn start(self, mut rx: Receiver<()>) {
loop {
self.task.run().await;
let _ = rx.try_recv();
let _ = timeout(self.interval, rx.recv()).await;
tokio::time::sleep(Duration::from_millis(100)).await;
}
}
}