Rust定时任务调度库clokwerk的使用:轻量级、高效的时间管理和周期性任务调度

Rust定时任务调度库clokwerk的使用:轻量级、高效的时间管理和周期性任务调度

Clokwerk是一个简单的调度库,灵感来自Python的Schedule和Ruby的clockwork。它使用类似的DSL进行调度,而不是解析cron字符串。

默认情况下,时间和日期是相对于本地时区的,但可以使用Scheduler::with_tz构造函数让调度器使用不同的时区。

从0.4版本开始,Clokwerk还支持单独的AsyncScheduler,它可以轻松地并发运行异步任务。

使用示例

// 引入调度器和时间单位特性
use clokwerk::{Scheduler, TimeUnits};
// 引入星期和WeekDay
use clokwerk::Interval::*;
use std::thread;
use std::time::Duration;

// 创建一个新的调度器
let mut scheduler = Scheduler::new();
// 或者创建一个指定时区的调度器
let mut scheduler = Scheduler::with_tz(chrono::Utc);
// 添加一些任务
scheduler.every(10.minutes()).plus(30.seconds()).run(|| println!("周期性任务"));
scheduler.every(1.day()).at("3:20 pm").run(|| println!("每日任务"));
scheduler.every(Tuesday).at("14:20:17").and_every(Thursday).at("15:00").run(|| println!("双周任务"));

// 在事件循环中手动运行调度器
for _ in 1..10 {
    scheduler.run_pending();
    thread::sleep(Duration::from_millis(10));
}
// 或者在后台线程中运行
let thread_handle = scheduler.watch_thread(Duration::from_millis(100));
// 当`thread_handle`被丢弃或调用`stop`时,调度器会停止
thread_handle.stop();

完整示例代码

use clokwerk::{Scheduler, TimeUnits};
use clokwerk::Interval::*;
use std::thread;
use std::time::Duration;

fn main() {
    // 创建调度器
    let mut scheduler = Scheduler::new();

    // 添加各种定时任务
    // 每隔10分钟30秒执行一次
    scheduler.every(10.minutes())
             .plus(30.seconds())
             .run(|| println!("执行周期性任务 - 每10分30秒"));

    // 每天下午3:20执行
    scheduler.every(1.day())
             .at("3:20 pm")
             .run(|| println!("执行每日任务 - 下午3:20"));

    // 每周二14:20:17和每周四15:00执行
    scheduler.every(Tuesday)
             .at("14:20:17")
             .and_every(Thursday)
             .at("15:00")
             .run(|| println!("执行双周任务 - 周二14:20:17或周四15:00"));

    // 在事件循环中运行调度器
    loop {
        scheduler.run_pending();
        thread::sleep(Duration::from_millis(100));
    }
}

类似库

  • schedule-rs和job_scheduler是另外两个Rust调度库。它们都使用cron语法进行调度。

安装

在Cargo.toml中添加:

clokwerk = "0.4.0"

或者运行:

cargo add clokwerk

完整示例demo

下面是一个更完整的clokwerk使用示例,包含异步任务调度和错误处理:

use clokwerk::{AsyncScheduler, Scheduler, TimeUnits};
use clokwerk::Interval::*;
use std::sync::Arc;
use tokio::sync::Mutex;
use std::time::Duration;

#[tokio::main]
async fn main() {
    // 同步调度器示例
    let mut sync_scheduler = Scheduler::new();
    
    // 添加同步任务
    sync_scheduler.every(30.seconds()).run(|| {
        println!("同步任务执行 - 每30秒");
    });
    
    // 异步调度器示例
    let async_scheduler = Arc::new(Mutex::new(AsyncScheduler::new()));
    
    // 添加异步任务
    {
        let mut scheduler = async_scheduler.lock().await;
        scheduler.every(1.minutes()).run(|| async {
            println!("异步任务执行 - 每分钟");
        });
    }
    
    // 在后台线程中运行同步调度器
    let sync_thread = sync_scheduler.watch_thread(Duration::from_millis(100));
    
    // 运行异步调度器
    tokio::spawn(async move {
        let scheduler = async_scheduler.clone();
        loop {
            scheduler.lock().await.run_pending().await;
            tokio::time::sleep(Duration::from_millis(100)).await;
        }
    });
    
    // 主线程等待
    tokio::signal::ctrl_c().await.expect("无法监听Ctrl+C信号");
    sync_thread.stop();
    println!("调度器已停止");
}

Clokwerk是一个轻量级但功能强大的定时任务调度库,特别适合需要简单但灵活的任务调度场景。通过直观的DSL语法,开发者可以轻松设置各种复杂的定时任务,而无需学习复杂的cron表达式。


1 回复

Rust定时任务调度库clokwerk使用指南

概述

clokwerk是一个轻量级、高效的Rust定时任务调度库,提供了简单直观的API来管理周期性任务。它特别适合需要执行定时任务的应用程序,如定时数据清理、周期性数据同步等场景。

主要特性

  • 轻量级设计,无额外依赖
  • 直观的API设计
  • 支持多种时间间隔设置
  • 线程安全
  • 可暂停和恢复调度器

基本使用方法

添加依赖

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

[dependencies]
clokwerk = "0.4"

基本示例

use clokwerk::{Scheduler, TimeUnits};
use std::thread;
use std::time::Duration;

fn main() {
    // 创建调度器
    let mut scheduler = Scheduler::new();

    // 定义任务
    scheduler.every(10.seconds()).run(|| println!("每10秒执行一次"));
    scheduler.every(1.minutes()).run(|| println!("每分钟执行一次"));
    scheduler.every(1.day()).at("12:00").run(|| println!("每天中午12点执行"));

    // 在后台线程中运行调度器
    thread::spawn(move || {
        loop {
            scheduler.run_pending();
            thread::sleep(Duration::from_millis(100));
        }
    });

    // 主线程继续执行其他工作
    println!("调度器已在后台运行,主线程继续...");
    thread::sleep(Duration::from_secs(60));
}

高级用法

指定具体时间执行

scheduler.every(1.day()).at("15:30:20").run(|| {
    println!("每天15:30:20执行");
});

工作日调度

use clokwerk::Interval::Weekday;

scheduler.every(Weekday).at("09:00").run(|| {
    println!("每个工作日早上9点执行");
});

暂停和恢复调度器

// 暂停调度器
scheduler.pause();

// 恢复调度器
scheduler.resume();

带参数的闭包

let name = "Rust".to_string();
scheduler.every(10.seconds()).run(move || {
    println!("Hello, {}!", name);
});

时间间隔选项

clokwerk提供了多种时间间隔设置方式:

  • .seconds()
  • .minutes()
  • .hours()
  • .days()
  • .weeks()
  • .weekday() (特定星期几)
  • .monday()/.tuesday()等 (具体星期几)

完整示例代码

下面是一个结合了多种特性的完整示例:

use clokwerk::{Scheduler, TimeUnits, Interval};
use std::thread;
use std::time::Duration;

fn main() {
    // 创建调度器实例
    let mut scheduler = Scheduler::new();
    
    // 1. 基本定时任务 - 每5秒执行一次
    scheduler.every(5.seconds()).run(|| {
        println!("基本定时任务: 每5秒执行");
    });

    // 2. 指定具体时间执行 - 每天14:25执行
    scheduler.every(1.day()).at("14:25").run(|| {
        println!("指定时间任务: 每天14:25执行");
    });

    // 3. 工作日任务 - 每周一至周五9:30执行
    scheduler.every(Interval::Weekday).at("09:30").run(|| {
        println!("工作日任务: 每个工作日9:30执行");
    });

    // 4. 带参数的闭包任务
    let count = 0;
    scheduler.every(30.seconds()).run(move || {
        println!("带参数的任务: 计数器值 = {}", count);
        // 注意: 由于闭包是move的,这里不能修改count
    });

    // 在后台线程中运行调度器
    let handle = thread::spawn(move || {
        loop {
            scheduler.run_pending();
            thread::sleep(Duration::from_millis(100));
        }
    });

    println!("调度器已启动,运行5分钟后停止...");
    
    // 主线程等待5分钟
    thread::sleep(Duration::from_secs(300));
    
    // 停止调度器(通过丢弃调度器)
    drop(handle);
    println!("调度器已停止");
}

注意事项

  1. 调度器本身不创建线程,需要手动在后台线程中运行
  2. 任务执行是同步的,长时间运行的任务会阻塞其他任务的执行
  3. 对于高精度定时需求,可能需要考虑其他方案

clokwerk以其简洁的API和轻量级的特性,成为Rust生态中定时任务调度的优秀选择,特别适合不需要分布式调度的简单应用场景。

回到顶部