use std::sync::Arc;
use clap::Subcommand;
use sz_orm_scheduler::Scheduler;
use crate::error::CliError;
#[derive(Subcommand, Debug)]
pub enum SchedulerCommand {
#[command(name = "list")]
List,
#[command(name = "run")]
Run,
#[command(name = "start")]
Start {
#[arg(short = 't', long, default_value = "1000")]
tick_ms: u64,
},
}
pub fn execute(cmd: &SchedulerCommand) -> Result<(), CliError> {
let scheduler = sz_orm_scheduler::CronScheduler::new();
match cmd {
SchedulerCommand::List => execute_list(&scheduler),
SchedulerCommand::Run => execute_run(&scheduler),
SchedulerCommand::Start { tick_ms } => execute_start(&scheduler, *tick_ms),
}
}
fn execute_list(scheduler: &sz_orm_scheduler::CronScheduler) -> Result<(), CliError> {
let tasks = scheduler.list_tasks();
if tasks.is_empty() {
println!("No scheduled tasks registered.");
println!();
println!("To register tasks, create a scheduler configuration file");
println!("or use the scheduler API in your application code.");
return Ok(());
}
println!(
"{:<15} {:<20} {:<25} {:<8}",
"ID", "Name", "Cron", "Enabled"
);
println!("{}", "-".repeat(70));
for task in &tasks {
println!(
"{:<15} {:<20} {:<25} {:<8}",
task.id, task.name, task.cron_expr, task.enabled
);
}
println!();
println!("Total: {} task(s)", tasks.len());
Ok(())
}
fn execute_run(scheduler: &sz_orm_scheduler::CronScheduler) -> Result<(), CliError> {
let now = chrono::Utc::now();
let fired = scheduler.try_fire_due(now);
println!("Scheduler run: {} task(s) fired at {}", fired, now);
Ok(())
}
fn execute_start(
scheduler: &sz_orm_scheduler::CronScheduler,
tick_ms: u64,
) -> Result<(), CliError> {
println!("Starting scheduler with tick interval: {}ms", tick_ms);
println!("Press Ctrl+C to stop.");
register_demo_tasks(scheduler)?;
scheduler
.start(tick_ms)
.map_err(|e| CliError::Scheduler(e.to_string()))?;
println!("Scheduler started. Waiting for tasks to fire...");
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
fn register_demo_tasks(scheduler: &sz_orm_scheduler::CronScheduler) -> Result<(), CliError> {
let task1 = sz_orm_scheduler::ScheduledTask::new("demo-1", "每分钟任务", "0 * * * *")
.with_callback("demo::minute_task");
scheduler
.schedule(task1)
.map_err(|e| CliError::Scheduler(e.to_string()))?;
let task2 = sz_orm_scheduler::ScheduledTask::new("demo-2", "每小时任务", "0 0 * * *")
.with_callback("demo::hourly_task");
scheduler
.schedule(task2)
.map_err(|e| CliError::Scheduler(e.to_string()))?;
let handler: Arc<dyn sz_orm_scheduler::JobHandler> = Arc::new(DemoJobHandler);
scheduler.register_handler("demo-1", handler.clone());
scheduler.register_handler("demo-2", handler);
println!("Registered 2 demo tasks (demo-1, demo-2)");
Ok(())
}
struct DemoJobHandler;
impl sz_orm_scheduler::JobHandler for DemoJobHandler {
fn handle(&self, task: &sz_orm_scheduler::ScheduledTask) -> Result<(), String> {
println!(
"[{}] Task fired: {} ({})",
chrono::Utc::now(),
task.name,
task.id
);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use sz_orm_scheduler::JobHandler;
use sz_orm_scheduler::Scheduler;
#[test]
fn test_execute_list_empty() {
let scheduler = sz_orm_scheduler::CronScheduler::new();
let result = execute_list(&scheduler);
assert!(result.is_ok());
}
#[test]
fn test_execute_list_with_tasks() {
let scheduler = sz_orm_scheduler::CronScheduler::new();
let task = sz_orm_scheduler::ScheduledTask::new("test-1", "测试任务", "0 * * * *");
scheduler.schedule(task).unwrap();
let result = execute_list(&scheduler);
assert!(result.is_ok());
}
#[test]
fn test_execute_run() {
let scheduler = sz_orm_scheduler::CronScheduler::new();
let result = execute_run(&scheduler);
assert!(result.is_ok());
}
#[test]
fn test_register_demo_tasks() {
let scheduler = sz_orm_scheduler::CronScheduler::new();
let result = register_demo_tasks(&scheduler);
assert!(result.is_ok());
let tasks = scheduler.list_tasks();
assert_eq!(tasks.len(), 2);
}
#[test]
fn test_register_demo_tasks_with_invalid_cron() {
let scheduler = sz_orm_scheduler::CronScheduler::new();
let task = sz_orm_scheduler::ScheduledTask::new("bad", "bad", "");
let result = scheduler.schedule(task);
assert!(result.is_err());
}
#[test]
fn test_demo_job_handler() {
let handler = DemoJobHandler;
let task = sz_orm_scheduler::ScheduledTask::new("test", "测试", "0 * * * *");
let result = handler.handle(&task);
assert!(result.is_ok());
}
}