Rust定时任务管理库delay_timer的使用,轻量级高性能的延迟任务调度与执行工具

Rust定时任务管理库delay_timer的使用,轻量级高性能的延迟任务调度与执行工具

delay-timer是一个基于时间轮算法的任务管理器,可以轻松管理定时任务或定期执行任意任务(如闭包)。底层运行时基于可选的smol和tokio,您可以选择其中任何一个来构建您的应用程序。

主要特性

  • 支持配置任务的最大并行数
  • 通过句柄动态取消正在运行的任务实例
  • 支持同步和异步任务
  • 可以指定具体日期执行任务(如每周日凌晨4点执行备份任务)
  • 最小支持的rustc版本是1.56

示例代码

基础使用示例

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

fn main() -> Result<()> {
    // 构建一个使用Smol运行时默认配置的DelayTimer
    let delay_timer = DelayTimerBuilder::default().build();

    // 开发一个异步循环运行的打印任务
    let task_instance_chain = delay_timer.insert_task(build_task_async_print()?)?;

    // 获取任务1的运行实例
    let task_instance = task_instance_chain.next_with_wait()?;

    // 取消正在运行的任务实例
    task_instance.cancel_with_wait()?;

    // 移除ID为1的任务
    delay_timer.remove_task(1)?;

    // 不再接受新任务;运行中的任务不受影响
    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<()> {
    // 构建一个使用Smol运行时默认配置的DelayTimer
    let delay_timer = DelayTimerBuilder::default().build();

    // 开发一个异步循环运行的打印任务
    let task_instance_chain = delay_timer.insert_task(build_task_async_print()?)?;

    // 获取任务1的运行实例
    let task_instance = task_instance_chain.next_with_async_wait().await?;

    // 取消正在运行的任务实例
    task_instance.cancel_with_async_wait().await?;

    // 移除ID为1的任务
    delay_timer.remove_task(1)?;

    // 不再接受新任务;运行中的任务不受影响
    delay_timer.stop_delay_timer()
}

fn build_task_async_print() -> Result<Tail, 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(())
}

完整示例Demo

以下是一个完整的定时任务示例,展示了如何创建一个周期性执行的HTTP请求任务:

use delay_timer::prelude::*;
use anyhow::Result;
use surf; // HTTP客户端
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<()> {
    // 创建延迟定时器
    let delay_timer = DelayTimerBuilder::default().build();
    
    // 创建HTTP请求任务
    let task = build_http_task()?;
    
    // 添加任务到定时器
    delay_timer.insert_task(task)?;
    
    // 让主线程等待一段时间,观察任务执行
    tokio::time::sleep(Duration::from_secs(30)).await;
    
    Ok(())
}

fn build_http_task() -> Result<Task, TaskError> {
    let mut task_builder = TaskBuilder::default();
    
    // 定义任务体 - 每5秒发送一次HTTP请求
    let body = || async {
        println!("准备发送HTTP请求...");
        
        match surf::get("https://httpbin.org/get").await {
            Ok(mut res) => {
                println!("响应状态: {}", res.status());
                if let Ok(body) = res.body_string().await {
                    println!("响应内容: {}", body);
                }
            }
            Err(e) => eprintln!("请求失败: {}", e),
        }
    };
    
    task_builder
        .set_task_id(1)
        .set_frequency_repeated_by_cron_str("*/5 * * * * *") // 每5秒执行一次
        .set_maximum_parallel_runnable_num(1)
        .spawn_async_routine(body)
}

许可证

delay-timer采用MIT或Apache-2.0双许可证授权。


1 回复

Rust定时任务管理库delay_timer使用指南

简介

delay_timer是一个轻量级高性能的Rust延迟任务调度与执行工具库,专为需要定时任务管理的应用场景设计。它提供了简单易用的API来安排延迟执行或周期性执行的任务。

主要特性

  • 轻量级设计,低资源占用
  • 高性能任务调度
  • 支持一次性延迟任务和周期性任务
  • 线程安全的任务管理
  • 简单的API接口

基本使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
delay_timer = "0.11"

创建定时器实例

use delay_timer::prelude::*;

fn main() {
    // 创建定时器实例
    let timer = DelayTimerBuilder::default().build();
    
    // 或者使用自定义配置
    let timer = DelayTimerBuilder::default()
        .tokio_runtime_by_default()
        .build()
        .unwrap();
}

添加一次性任务

async fn one_shot_task() {
    println!("This task runs once after delay");
}

fn main() {
    let timer = DelayTimerBuilder::default().build().unwrap();
    
    let task = TaskBuilder::default()
        .set_task_id(1)
        .set_frequency(Frequency::Once)
        .set_maximun_parallel_runable_num(1)
        .spawn(one_shot_task())
        .unwrap();
    
    timer.add_task(task).unwrap();
}

添加周期性任务

async fn periodic_task() {
    println!("This task runs periodically");
}

fn main() {
    let timer = DelayTimerBuilder::default().build().unwrap();
    
    let task = TaskBuilder::default()
        .set_task_id(2)
        .set_frequency(Frequency::Repeated("*/5 * * * * *"))
        .set_maximun_parallel_runable_num(1)
        .spawn(periodic_task())
        .unwrap();
    
    timer.add_task(task).unwrap();
}

高级用法

带参数的任务

async fn task_with_args(arg: i32) {
    println!("Task received argument: {}", arg);
}

fn main() {
    let timer = DelayTimerBuilder::default().build().unwrap();
    
    let task = TaskBuilder::default()
        .set_task_id(3)
        .set_frequency(Frequency::Once)
        .set_maximun_parallel_runable_num(1)
        .spawn(async {
            task_with_args(42).await;
        })
        .unwrap();
    
    timer.add_task(task).unwrap();
}

动态取消任务

fn main() {
    let timer = DelayTimerBuilder::default().build().unwrap();
    
    // 添加任务并获取任务句柄
    let task = TaskBuilder::default()
        .set_task_id(4)
        .set_frequency(Frequency::Repeated("*/10 * * * * *"))
        .set_maximun_parallel_runable_num(1)
        .spawn(async {
            println!("This task will be cancelled");
        })
        .unwrap();
    
    let task_id = task.get_task_id();
    timer.add_task(task).unwrap();
    
    // 稍后取消任务
    std::thread::sleep(std::time::Duration::from_secs(30));
    timer.remove_task(task_id).unwrap();
}

完整示例

下面是一个完整的示例,演示如何使用delay_timer创建和管理定时任务:

use delay_timer::prelude::*;
use std::time::Duration;

// 一次性任务
async fn one_time_job() {
    println!("一次性任务执行了!");
}

// 周期性任务
async fn periodic_job() {
    println!("周期性任务执行了!");
}

// 带参数的任务
async fn job_with_params(name: &str, count: i32) {
    println!("任务'{}'执行了{}次", name, count);
}

#[tokio::main]
async fn main() {
    // 创建定时器实例
    let timer = DelayTimerBuilder::default()
        .tokio_runtime_by_default()
        .build()
        .unwrap();

    // 添加一次性任务(10秒后执行)
    let one_time_task = TaskBuilder::default()
        .set_task_id(1)
        .set_frequency(Frequency::Once)
        .set_maximum_parallel_runnable_num(1)
        .spawn(one_time_job())
        .unwrap();
    timer.add_task(one_time_task).unwrap();

    // 添加周期性任务(每5秒执行一次)
    let periodic_task = TaskBuilder::default()
        .set_task_id(2)
        .set_frequency(Frequency::Repeated("*/5 * * * * *"))
        .set_maximum_parallel_runnable_num(1)
        .spawn(periodic_job())
        .unwrap();
    timer.add_task(periodic_task).unwrap();

    // 添加带参数的任务
    let param_task = TaskBuilder::default()
        .set_task_id(3)
        .set_frequency(Frequency::Repeated("*/8 * * * * *"))
        .set_maximum_parallel_runnable_num(1)
        .spawn(async {
            job_with_params("测试任务", 3).await;
        })
        .unwrap();
    timer.add_task(param_task).unwrap();

    // 让程序运行一段时间
    tokio::time::sleep(Duration::from_secs(30)).await;

    // 清理所有任务
    timer.remove_all_tasks().unwrap();
}

注意事项

  1. 确保任务函数是Send + 'static
  2. 对于长时间运行的任务,考虑使用tokio::spawn在任务内部
  3. 合理设置maximun_parallel_runable_num以避免资源耗尽

delay_timer是构建需要定时任务功能的Rust应用的强大工具,它的简单API和高效实现使其成为许多场景下的理想选择。

回到顶部