#cron #task-scheduling #delay #scheduler #timer #task-manager

delay_timer

延迟任务的时间管理器。类似于 crontab,但支持同步异步任务,并支持动态添加/取消/删除。

28 个版本

0.11.6 2024 年 5 月 20 日
0.11.5 2024 年 1 月 8 日
0.11.4 2023 年 3 月 21 日
0.11.3 2022 年 5 月 17 日
0.1.0 2020 年 11 月 11 日

#103异步

Download history 1440/week @ 2024-04-26 1393/week @ 2024-05-03 1386/week @ 2024-05-10 1777/week @ 2024-05-17 1920/week @ 2024-05-24 2129/week @ 2024-05-31 1829/week @ 2024-06-07 2194/week @ 2024-06-14 1549/week @ 2024-06-21 1759/week @ 2024-06-28 1531/week @ 2024-07-05 1561/week @ 2024-07-12 1447/week @ 2024-07-19 1188/week @ 2024-07-26 961/week @ 2024-08-02 822/week @ 2024-08-09

4,605 每月下载量
用于 rusty_vault

Apache-2.0 OR MIT

185KB
3.5K SLoC

delay-timer

Build License Cargo Documentation

延迟任务的时间管理器。类似于 crontab,但支持同步异步任务,并支持动态添加/取消/删除。

delay-timer 是一个基于时间轮算法的任务管理器,它使得管理定时任务或周期性地执行任意任务(如闭包)变得容易。

底层运行时基于可选的 smol 和 tokio,您可以使用其中任何一个来构建您的应用程序。

rustc 的最低支持版本是 1.56

除了简单的几秒内执行外,您还可以指定特定的日期和时间,例如周日在凌晨 4 点执行备份任务。

支持配置任务的并行度。
通过句柄动态取消正在运行的任务实例。

image

如果您正在寻找分布式任务调度平台,请查看 delicate

示例


use anyhow::Result;
use delay_timer::prelude::*;

fn main() -> Result<()> {
   // Build an DelayTimer that uses the default configuration of the Smol runtime internally.
   let delay_timer = DelayTimerBuilder::default().build();

   // Develop a print job that runs in an asynchronous cycle.
   // A chain of task instances.
   let task_instance_chain = delay_timer.insert_task(build_task_async_print()?)?;

   // Get the running instance of task 1.
   let task_instance = task_instance_chain.next_with_wait()?;

   // Cancel running task instances.
   task_instance.cancel_with_wait()?;

   // Remove task which id is 1.
   delay_timer.remove_task(1)?;

   // No new tasks are accepted; running tasks are not affected.
   delay_timer.stop_delay_timer()?;

   Ok(())
}

fn build_task_async_print() -> Result<Task, TaskError> {
   let mut task_builder = TaskBuilder::default();

   let body = || async {
       println!("create_async_fn_body!");

       Timer::after(Duration::from_secs(3)).await;

       println!("create_async_fn_body:i'success");
   };

   task_builder
       .set_task_id(1)
       .set_frequency_repeated_by_cron_str("@secondly")
       .set_maximum_parallel_runnable_num(2)
       .spawn_async_routine(body)
}

在异步上下文中使用。


use delay_timer::prelude::*;

use anyhow::Result;

use smol::Timer;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<()> {
   // In addition to the mixed (smol & tokio) runtime
   // You can also share a tokio runtime with delayTimer, please see api `DelayTimerBuilder::tokio_runtime` for details.

   // Build an DelayTimer that uses the default configuration of the Smol runtime internally.
   let delay_timer = DelayTimerBuilder::default().build();

   // Develop a print job that runs in an asynchronous cycle.
   let task_instance_chain = delay_timer.insert_task(build_task_async_print()?)?;

   // Get the running instance of task 1.
   let task_instance = task_instance_chain.next_with_async_wait().await?;

   // Cancel running task instances.
   task_instance.cancel_with_async_wait().await?;


   // Remove task which id is 1.
   delay_timer.remove_task(1)?;

   // No new tasks are accepted; running tasks are not affected.
   delay_timer.stop_delay_timer()
}

fn build_task_async_print() -> Result<Task, TaskError> {
   let mut task_builder = TaskBuilder::default();

   let body = || async {
       println!("create_async_fn_body!");

       Timer::after(Duration::from_secs(3)).await;

       println!("create_async_fn_body:i'success");
   };

   task_builder
       .set_task_id(1)
       .set_frequency_repeated_by_cron_str("@secondly")
       .set_maximum_parallel_runnable_num(2)
       .spawn_async_routine(body)
}

捕获指定环境信息并构建闭包和任务

#[macro_use]
use delay_timer::prelude::*;

use std::sync::atomic::{
    AtomicUsize,
    Ordering::{Acquire, Release},
};
use std::sync::Arc;


let delay_timer = DelayTimer::new();
let share_num = Arc::new(AtomicUsize::new(0));
let share_num_bunshin = share_num.clone();

let body = move || {
    share_num_bunshin.fetch_add(1, Release);
};

let task = TaskBuilder::default()
    .set_frequency_count_down_by_cron_str(expression, 3)
    .set_task_id(1)
    .spawn_routine(body)?;

delay_timer.add_task(task)?;

构建自定义的动态未来任务

#[macro_use]
use delay_timer::prelude::*;
use hyper::{Client, Uri};

fn build_task_customized_async_task() -> Result<Task, TaskError> {
   let id = 1;
   let name = String::from("someting");
   let mut task_builder = TaskBuilder::default();

   let body = move || {
       let name_ref = name.clone();
       async move {
           async_template(id, name_ref).await.expect("Request failed.");

           sleep(Duration::from_secs(3)).await;

           println!("create_async_fn_body:i'success");
       }
   };

   task_builder
       .set_frequency_repeated_by_cron_str("0,10,15,25,50 0/1 * * Jan-Dec * 2020-2100")
       .set_task_id(5)
       .set_maximum_running_time(5)
       .spawn_async_routine(body)
}


pub async fn async_template(id: i32, name: String) -> Result<()> {
   let url = format!("https://httpbin.org/get?id={}&name={}", id, name);
   let mut res = surf::get(url).await?;
   dbg!(res.body_string().await?);

   Ok(())
}

在 [examples] 目录中还有更多内容。

许可证

许可协议为

待办事项列表

  • 支持 tokio 生态。
  • 禁用将导致 panic 的 unwrap 相关方法。
  • 当 delayTimer 释放时,线程和正在运行的任务退出。
  • 整理代码中的 todo,补充测试和基准。
  • 批处理操作。
  • 服务器报告。
  • 将 delay_timer 升级到多轮模式,不同的执行器处理不同的轮次,例如为某个轮次减去圈数,为某个轮次运行任务。

贡献

除非您明确声明,否则任何有意提交给工作以包括在内的贡献,根据 Apache-2.0 许可证定义,应按上述方式双许可,不附加任何额外条款或条件。

依赖项

~11–25MB
~312K SLoC