4 releases
0.1.3 | Jun 25, 2024 |
---|---|
0.1.2 | Jun 20, 2024 |
0.1.1 | Jun 12, 2024 |
0.1.0 | Jun 9, 2024 |
#147 in Concurrency
66 downloads per month
Used in 4 crates
(via asteroid-mq)
43KB
1K
SLoC
Tsuki-Scheduler
A simple, light wight, composable and extensible scheduler for every runtime.
Scheduler = Schedule × Runtime
Usage
This small crate can help you running tasks in
- tokio
- async-std
- new thread
- local
- promise
- and more as long as the way to create a task in this runtime is implemented.
with a combination of
- cron schedule
- once or periodically
- after or before some time
- utc date-time iterator
- and more as long as it implement a trait
Schedule
.
For a more detailed document, check the rust doc.
cargo add tsuki-scheduler
or
tsuki-scheduler = "0.1"
Create scheduler
use tsuki_scheduler::prelude::*;
let mut scheduler = Scheduler::new(Tokio);
let mut scheduler = Scheduler::new(AsyncStd);
let mut scheduler = Scheduler::new(Promise);
let mut scheduler = Scheduler::new(Thread);
// or you may use the async wrapper
let mut scheduler_runner = AsyncSchedulerRunner::<Tokio>::default();
let client = scheduler_runner.client();
Compose schedules
What if I want to create a very complex schedule like this:
- Firstly it will run at 10 seconds later.
- And then, it will run at every hour's 10th minute.
- Meanwhile, it will run every 80 minutes.
- Though, it won't run within 30 minutes after the last run.
- Finally, it will stop running after 100 days later.
And you can actually do it:
use tsuki_scheduler::prelude::*;
use chrono::TimeDelta;
let start_time = now() + TimeDelta::seconds(10);
let schedule = Once::new(start_time)
.then(
Cron::utc_from_cron_expr("00 10 * * * *")
.expect("invalid cron")
.or(Period::new(
TimeDelta::minutes(80),
start_time + TimeDelta::minutes(80),
))
.throttling(TimeDelta::minutes(30)),
)
.before(start_time + TimeDelta::days(100));
For some case you want to use a certain type for all schedule, you can use Box<dyn Schedule>
, and there's a builder api for it.
use tsuki_scheduler::prelude::*;
use chrono::{Utc, TimeDelta};
let cron_list = Vec::<Cron<Utc>>::new();
// add some cron expr
// ...
// build schedule
let start_time = now() + TimeDelta::seconds(10);
let mut schedule_builder = Once::new(start_time).dyn_builder()
.then(
Cron::utc_from_cron_expr("00 10 * * * *")
.expect("invalid cron")
.or(Period::new(
TimeDelta::minutes(80),
start_time + TimeDelta::minutes(80),
))
.throttling(TimeDelta::minutes(30)),
)
.before(start_time + TimeDelta::days(100));
// collect all cron expr
schedule_builder = cron_list.into_iter().fold(schedule_builder, ScheduleDynBuilder::or);
let schedule = schedule_builder.build();
Add executes and delete tasks
use tsuki_scheduler::prelude::*;
let mut scheduler = Scheduler::new(Tokio);
let hello_tsuki_task = Task::tokio(
Cron::local_from_cron_expr("*/2 * * * * *").unwrap(),
|| async {
println!("Hello, tsuki!");
},
);
let id = TaskUid::uuid();
scheduler.add_task(id, hello_tsuki_task);
scheduler.execute_by_now();
scheduler.delete_task(id);
Manage the handles
You may ignore all the task handles, if you want to manage the handles, implement your own manager by implementing the trait HandleManager
.
Async runtime
In a async runtime, you may spawn a task for scheduler to execute periodically driven by event loop. This crate provides an implementation, you can check the example for tokio runtime.
Feature flags
flag | description |
---|---|
uuid | allow to create TaskUid by uuid-v4 |
cron | allow to create a schedule described by a cron expression |
tokio | enable tokio runtime |
async_std | enable async_std runtime |
thread | enable thread runtime |
promise | enable js promise runtime |
async-scheduler | a default async wrapper for async runtime |
Alternative crates
Dependencies
~1–13MB
~160K SLoC