use tokio::time::{sleep, Duration};
use std::time::{SystemTime, UNIX_EPOCH};
pub struct AlignedTaskScheduler {
interval_minutes: u64,
offset_seconds: u64,
}
impl AlignedTaskScheduler {
pub fn new(interval_minutes: u64, offset_seconds: u64) -> Self {
AlignedTaskScheduler { interval_minutes, offset_seconds }
}
pub async fn run<F, Fut>(&self, mut task: F) -> !
where
F: FnMut(u64) -> Fut + Send + 'static,
Fut: std::future::Future<Output = ()> + Send + 'static,
{
loop {
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
let interval_secs = self.interval_minutes * 60;
let next_interval = ((now / interval_secs) + 1) * interval_secs;
let wait_secs_to_interval = next_interval - now;
sleep(Duration::from_secs(wait_secs_to_interval)).await;
if self.offset_seconds > 0 {
sleep(Duration::from_secs(self.offset_seconds)).await;
}
task(next_interval).await;
}
}
}