1 unstable release
| 0.2.1 | Nov 3, 2025 |
|---|
#1110 in Asynchronous
105KB
1.5K
SLoC
Cronline
Cronline is a minimalist yet powerful cron-style task scheduler built with Rust. Designed for simplicity, performance, and ease of integration, Cronline enables developers to effortlessly manage scheduled asynchronous tasks within Rust applications.
Purpose
Cronline addresses the common need among Rust developers for reliable task scheduling without the overhead of external cron utilities or complex frameworks. It's ideal for:
- Web services
- Automation tools
- Background job management
- Bots
- Microservices
Core Features
- Cron-like Scheduling: Intuitive scheduling using cron syntax (
0 0 * * *) - Interval-based Scheduling: Simple interval-based task execution with
Task::with_interval() - Async-Await Native: First-class async task support leveraging Tokio
- Task Tags/Labels: Organize and filter tasks using tags
- Graceful Cancellation: Cancel running tasks cleanly
- Timeout Warnings: Get warned at 80% of timeout duration
- Event Bus: Subscribe to scheduler and task lifecycle events
- Auto-generated Names: Meaningful task names automatically generated from cron expressions
- Robust Logging: Built-in logging integration (
log,env_logger, ortracing) - Fault-Tolerance & Retries: Configurable error handling and automatic task retries
- Simple & Modular: Easy to include and extend in existing Rust codebases
Installation
Add Cronline to your Cargo.toml:
[dependencies]
cronline = "0.2.1"
Basic Usage
use cronline::{Scheduler, Task};
use tokio;
#[tokio::main]
async fn main() {
// Create a new scheduler
let scheduler = Scheduler::new();
// Add a task that runs every day at 6am
scheduler.add("0 6 * * *", Task::new(|| async {
println!("Performing daily maintenance task...");
// Task implementation here
Ok(())
})).await.unwrap();
// Start the scheduler (this blocks until the scheduler is stopped)
scheduler.run().await;
}
Advanced Usage
use cronline::{Scheduler, Task, TaskConfig, SchedulerConfig};
use std::time::Duration;
#[tokio::main]
async fn main() {
// Create a scheduler with custom configuration
let scheduler = Scheduler::with_config(SchedulerConfig {
check_interval: Duration::from_millis(100),
continue_on_error: true,
shutdown_grace_period: Duration::from_secs(10),
});
// Add a task with custom retry configuration
scheduler.add("*/5 * * * *", Task::new(|| async {
// Task that runs every 5 minutes
// ...
Ok(())
})
.with_name("Background Process")
.with_config(TaskConfig {
timeout: Some(Duration::from_secs(60)),
max_retries: 3,
retry_delay: Duration::from_secs(5),
fail_scheduler_on_error: false,
})).await.unwrap();
// Start the scheduler in the background
scheduler.start().await.unwrap();
// Do other work...
// Stop the scheduler when done
scheduler.stop().await.unwrap();
}
Enhanced Features
Interval-based Scheduling
// Create a task that runs every 5 minutes
let task = Task::new(|| async {
println!("Running periodic task!");
Ok(())
})
.with_interval(Duration::from_secs(300));
scheduler.add_task(task).await?;
Task Tags and Filtering
// Create tasks with tags
let backup_task = Task::new(|| async { Ok(()) })
.with_tags(&["backup", "database", "critical"]);
let monitoring_task = Task::new(|| async { Ok(()) })
.with_tag("monitoring");
scheduler.add_task(backup_task)?;
scheduler.add_task(monitoring_task)?;
// Filter tasks by tags
let critical_tasks = scheduler.tasks_with_tag("critical").await;
let backup_or_monitoring = scheduler.tasks_with_any_tag(&["backup", "monitoring"]).await;
let critical_backups = scheduler.tasks_with_all_tags(&["backup", "critical"]).await;
Event Bus
// Subscribe to scheduler events
let mut events = scheduler.event_bus().subscribe();
tokio::spawn(async move {
while let Ok(event) = events.recv().await {
match event {
SchedulerEvent::TaskStarting { task_name, .. } => {
println!("Task starting: {}", task_name);
}
SchedulerEvent::TaskCompleted { task_name, duration_ms, .. } => {
println!("Task completed: {} ({}ms)", task_name, duration_ms);
}
SchedulerEvent::TaskTimeoutWarning { task_name, .. } => {
println!("Task approaching timeout: {}", task_name);
}
_ => {}
}
}
});
Task Cancellation
// Cancel a running task
if let Some(task) = scheduler.get_task(&task_id).await {
task.cancel().await;
}
Auto-generated Task Names
// Task names are automatically generated from cron expressions
let task = Task::new(|| async { Ok(()) })
.with_schedule("0 * * * *")?; // Automatically named "Hourly"
let task = Task::new(|| async { Ok(()) })
.with_schedule("*/5 * * * *")?; // Automatically named "Every 5 Minutes"
let task = Task::new(|| async { Ok(()) })
.with_interval(Duration::from_secs(300)); // Automatically named "Every 5 Minutes"
Task Management
// Get a list of all task IDs
let task_ids = scheduler.task_ids().await;
// Get a reference to a specific task
if let Some(task) = scheduler.get_task(&task_id).await {
// Get task statistics
let stats = task.stats().await;
println!("Task executions: {}", stats.executions);
// Manually execute a task
task.execute().await.unwrap();
// Pause a task
task.pause().await.unwrap();
// Resume a paused task
task.resume().await.unwrap();
// Cancel a running task
task.cancel().await;
}
// Remove a task from the scheduler
scheduler.remove(&task_id).unwrap();
Cron Expression Syntax
Cronline uses standard cron syntax: * * * * * (minute, hour, day of month, month, day of week)
Examples:
* * * * *- Every minute0 * * * *- Every hour at minute 00 0 * * *- Every day at midnight0 12 * * MON-FRI- Weekdays at noon*/15 * * * *- Every 15 minutes
Real-World Examples
Cronline includes comprehensive real-world examples demonstrating production patterns:
- Web Integration - Axum web framework integration with background tasks
- Monitoring & Alerting - System monitoring with threshold-based alerts
- Database Maintenance - Automated backups, optimization, and cleanup
- API Polling - Rate-limited API polling and web scraping
- Notifications - Email campaigns, reminders, and multi-channel messaging
- Cache Warming - Proactive cache management and optimization
See EXAMPLES.md for detailed documentation of all examples.
Run any example with:
cargo run --example web_integration_axum
cargo run --example monitoring_alerting
Recent Enhancements (v0.1.1)
- ✅ Interval-based scheduling with
Task::with_interval(Duration) - ✅ Task tags/labels for grouping and filtering
- ✅ Graceful task cancellation
- ✅ Task timeout warnings at 80% of timeout
- ✅ Scheduler event bus for task/scheduler events
- ✅ Auto-generated meaningful names from cron expressions
Future Enhancements
- Task persistence with databases (SQLite, Redis)
- Interactive CLI for task management
- Web dashboard integration
- Task dependencies and workflows
- Distributed task scheduling
License
This project is licensed under the MIT License - see the LICENSE file for details.
Dependencies
~5–9.5MB
~149K SLoC