Rucron: A Pure Rust Implementation Job Scheduling Package.
Rucron is a lightweight job scheduler, it is similar to gocron or linux crontab, and it is very easy to use.
Now rucron is compatible with the smol and tokio.
Usage
Add this to your Cargo.toml
[dependencies]
rucron = { version = "0.1.5", features = [ "tokio" ] }
rucron = { version = "0.1.5", features = [ "smol" ] }
Quick start:
use rucron::{sync_execute, execute, EmptyTask, Metric, Scheduler};
use std::{error::Error, sync::atomic::Ordering};
use chrono::{Local, DateTime, Duration};
async fn foo() -> Result<(), Box<dyn Error>>{
println!("foo");
Ok(())
}
async fn bar() -> Result<(), Box<dyn Error>>{
println!("bar");
Ok(())
}
async fn ping() -> Result<(), Box<dyn Error>>{
println!("ping");
Ok(())
}
fn once(m: &Metric, last: &DateTime<Local>) -> Duration {
let n = m.n_scheduled.load(Ordering::Relaxed);
if n < 1 {
Duration::seconds(2)
} else if n == 1 {
Duration::seconds(last.timestamp() * 2)
} else {
Duration::seconds(0)
}
}
fn sync_task() -> Result<(), Box<dyn Error>> {
std::thread::sleep(std::time::Duration::from_secs(2));
println!("sync task");
Ok(())
}
#[tokio::main]
async fn main(){
let sch = Scheduler::<EmptyTask, ()>::new(1, 10);
let sch = sch
.every(1).second().todo(execute(foo)).await
.at().week(1, 9, 0, 0).todo(execute(bar)).await
.by(once).todo(execute(ping)).await
.every(2).second().todo(sync_execute(sync_task)).await;
sch.start().await;
}
Schedule parameterized job:
use rucron::{execute, ArgStorage, EmptyTask, ParseArgs, Scheduler};
use std::error::Error;
use async_trait::async_trait;
#[derive(Clone)]
struct Person {
age: i32,
}
#[async_trait]
impl ParseArgs for Person {
type Err = std::io::Error;
fn parse_args(args: &ArgStorage) -> Result<Self, Self::Err> {
return Ok(args.get::<Person>().unwrap().clone());
}
}
async fn is_eight_years_old(p: Person) -> Result<(), Box<dyn Error>> {
if p.age == 8 {
println!("I am eight years old!");
} else {
println!("Oops!");
};
Ok(())
}
#[tokio::main]
async fn main() {
let child = Person { age: 8 };
let mut arg = ArgStorage::new();
arg.insert(child);
let mut sch = Scheduler::<EmptyTask, ()>::new(1, 10);
sch.set_arg_storage(arg);
let sch = sch.every(2).second().todo(execute(is_eight_years_old)).await;
sch.start().await;
}
You could also schedule blocking or CPU-bound tasks.
use rucron::{sync_execute, ArgStorage, EmptyTask, ParseArgs, Scheduler};
use std::error::Error;
#[derive(Clone)]
struct Person {
age: i32,
}
impl ParseArgs for Person {
type Err = std::io::Error;
fn parse_args(args: &ArgStorage) -> Result<Self, Self::Err> {
Ok(args.get::<Person>().unwrap().clone())
}
}
fn sync_set_age(p: Person) -> Result<(), Box<dyn Error>> {
if p.age == 8 {
println!("I am eight years old!");
};
Ok(())
}
#[tokio::main]
async fn main() {
let child = Person { age: 8 };
let mut arg = ArgStorage::new();
arg.insert(child);
let mut sch = Scheduler::<EmptyTask, ()>::new(1, 10);
sch.set_arg_storage(arg);
let sch = sch.every(2).second().todo(sync_execute(sync_set_age)).await;
sch.start().await;
}
If you want to schedule jobs with distributed locks, please see [examples] directory.
License
Rucron is licensed under the MIT license.
Contributing
Contributions are welcome. Unless you explicitly state otherwise,
any contribution intentionally submitted for inclusion in the work by you, as defined in the MIT license, shall be dual licensed as above,
without any additional terms or conditions.