use log::info;
use simple_logger::SimpleLogger;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::Duration;
use tasklet::task::TaskStepStatusErr::Error;
use tasklet::task::TaskStepStatusOk::Success;
use tasklet::{RetryPolicy, TaskBuilder, TaskScheduler};
#[tokio::main]
async fn main() {
SimpleLogger::new().init().unwrap();
let attempts = Arc::new(AtomicUsize::new(0));
let step_attempts = attempts.clone();
let mut scheduler = TaskScheduler::new(250, chrono::Local);
let _ = scheduler.add_task(
TaskBuilder::new(chrono::Local)
.every("* * * * * * *")
.description("A flaky task guarded by a timeout and retries")
.repeat(1)
.timeout(Duration::from_secs(2))
.retry(
RetryPolicy::exponential(3, Duration::from_millis(100), 2)
.with_max_delay(Duration::from_secs(1)),
)
.on_success(|| async { info!("run succeeded") })
.on_failure(|| async { info!("run failed after exhausting retries") })
.on_finish(|| async { info!("task finished its lifecycle") })
.add_step("Flaky step", move || {
let attempts = step_attempts.clone();
async move {
let attempt = attempts.fetch_add(1, Ordering::SeqCst);
if attempt < 2 {
info!("attempt #{} failing, will be retried", attempt + 1);
Err(Error)
} else {
info!("attempt #{} succeeding", attempt + 1);
Ok(Success)
}
}
})
.build(),
);
scheduler
.run_until(tokio::time::sleep(Duration::from_secs(5)))
.await;
info!("total step attempts: {}", attempts.load(Ordering::SeqCst));
}