Planificador de tareas en Rust: desde un temporizador simple hasta un job scheduler industrial
Un planificador de tareas (job scheduler) es uno de los componentes clave de cualquier aplicación seria. En Rust, puede construir un sistema que se ejecute con precisión de milisegundos, consuma un mínimo de memoria y funcione sin fallos durante años. En este artículo, analizaremos cómo crear un planificador de tareas en Rust, utilizando tanto herramientas estándar como crates populares.
¿Por qué escribir un planificador en Rust?
Rust ofrece una combinación única de rendimiento y seguridad. Un planificador de tareas en Rust:
- Garantiza la ausencia de condiciones de carrera (data races) — el compilador lo verifica en tiempo de compilación.
- Funciona sin recolector de basura — latencia predecible en la ejecución de tareas.
- Admite tanto ejecución asíncrona como multiproceso.
- Tiene un consumo mínimo de memoria — puede ejecutar miles de tareas.
Planificador simple con std::thread::sleep
Comencemos con un ejemplo básico: ejecución cíclica de una tarea cada N segundos:
use std::thread;use std::time::Duration;
fn main() { let interval = Duration::from_secs(5); loop { println!("[{}] Ejecutando tarea...", chrono::Local::now().format("%H:%M:%S")); // Aquí el código de su tarea thread::sleep(interval); }}Este enfoque es simple pero ineficiente: bloquea el hilo actual y no permite ejecutar varias tareas en paralelo.
Planificador asíncrono con tokio
Para proyectos reales, use tokio — un runtime asíncrono que permite ejecutar miles de tareas en un solo hilo.
use tokio::time::{interval, Duration};
#[tokio::main]async fn main() { let mut timer = interval(Duration::from_secs(10)); println!("Planificador iniciado. La tarea se ejecutará cada 10 segundos."); loop { timer.tick().await; println!("[{}] Ejecutando tarea...", chrono::Local::now().format("%H:%M:%S")); // Tarea asíncrona: por ejemplo, una solicitud a una API do_work().await; }}
async fn do_work() { // Simulación de trabajo útil tokio::time::sleep(Duration::from_millis(500)).await; println!("Tarea completada.");}Ventajas: no bloquea el hilo, se pueden ejecutar cientos de estos planificadores en paralelo.
Programación tipo CRON con el crate cron
Si necesita programaciones complejas (como en Linux cron), use el crate cron:
use cron::Schedule;use chrono::Utc;use std::str::FromStr;
fn main() { // Cada minuto en el segundo 30 let expression = "30 * * * * *"; let schedule = Schedule::from_str(expression).unwrap(); println!("Próximas 5 ejecuciones:"); for datetime in schedule.upcoming(Utc).take(5) { println!(" {}", datetime); }}Aquí hay un ejemplo más completo con ejecución real:
use cron::Schedule;use chrono::{Utc, Local};use std::thread;use std::time::Duration;use std::str::FromStr;
fn main() { // Cada 15 segundos let expression = "0/15 * * * * *"; let schedule = Schedule::from_str(expression).unwrap(); loop { let now = Utc::now(); if let Some(next) = schedule.upcoming(Utc).next() { let delay = next - now; let millis = delay.num_milliseconds().max(0) as u64; thread::sleep(Duration::from_millis(millis)); println!("[{}] ¡Tarea programada!", Local::now().format("%H:%M:%S")); // Ejecución de la tarea } else { thread::sleep(Duration::from_secs(1)); } }}Planificador industrial con multiproceso
Para proyectos serios, cree una estructura Scheduler
También en la biblioteca
GraphQL en Kotlin: Reseña de bibliotecas y herramientas para desarrollo del lado del servidor
Trabajo con Markdown en Node.js: bibliotecas y herramientas para conversión
Trabajo con Kafka en Kotlin: bibliotecas y ejemplos
Validación de datos en Swift: biblioteca Validator