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!("调度器已停止");
}
注意事项
- 调度器本身不创建线程,需要手动在后台线程中运行
- 任务执行是同步的,长时间运行的任务会阻塞其他任务的执行
- 对于高精度定时需求,可能需要考虑其他方案
clokwerk以其简洁的API和轻量级的特性,成为Rust生态中定时任务调度的优秀选择,特别适合不需要分布式调度的简单应用场景。