مخطط المهام بلغة Rust: دليل كامل للمكتبات والتنفيذ
في التطوير الحديث لتطبيقات الخادم وأنظمة الأتمتة، يُعد مخطط المهام (task scheduler) أحد المكونات الرئيسية. تقدم Rust، بفضل أدائها وأمان الذاكرة، عدة حلول قوية لإنشاء مخططات مرنة وفعالة. في هذه المقالة، سنستعرض بالتفصيل المكتبات الرئيسية لجدولة المهام في Rust، وإمكانياتها، وأمثلة على استخدامها، ومقارنتها مع نظائرها في Python.
المكتبات الرئيسية لجدولة المهام في Rust
تقدم بيئة Rust عدة حلول ناضجة للعمل مع مخططات المهام. دعنا نستعرض ثلاث مكتبات الأكثر شيوعًا:
- tokio-schedule — مخطط غير متزامن يعتمد على tokio، يدعم تعبيرات cron والمهام الفاصلة
- cron — مكتبة خفيفة الوزن للعمل مع تعبيرات cron، تُستخدم غالبًا مع tokio
- async-task-scheduler — مخطط عالي المستوى مع دعم الأولويات، وإعادة المحاولة، وقواعد تشغيل معقدة
تثبيت وإعداد tokio-schedule
للبدء، أضف التبعيات إلى ملف Cargo.toml الخاص بك:
[dependencies]tokio = { version = "1.0", features = ["full"] }tokio-schedule = "0.4"chrono = "0.4"مثال 1: مخطط بسيط بفاصل زمني
لننشئ مخططًا أساسيًا ينفذ مهمة كل 5 ثوانٍ:
use tokio::time::{sleep, Duration};use tokio_schedule::Job;
#[tokio::main]async fn main() { // إنشاء مهمة يتم تنفيذها كل 5 ثوانٍ let job = Job::new() .every(Duration::from_secs(5)) .run(|| async { println!("تم تنفيذ المهمة في: {}", chrono::Local::now()); });
println!("تم تشغيل المخطط. اضغط Ctrl+C للإيقاف."); job.start().await; // انتظار لا نهائي loop { sleep(Duration::from_secs(1)).await; }}مثال 2: مخطط بتعبير cron
مثال أكثر تعقيدًا باستخدام صيغة cron للتحكم الدقيق في وقت التنفيذ:
use tokio_schedule::Job;use std::sync::Arc;use std::sync::atomic::{AtomicU64, Ordering};
#[tokio::main]async fn main() { let counter = Arc::new(AtomicU64::new(0)); let counter_clone = counter.clone();
// التشغيل كل دقيقة عند الثانية 30 let job = Job::new() .cron("30 * * * * *") // ثانية، دقيقة، ساعة، يوم، شهر، يوم_الأسبوع .run(move || { let cnt = counter_clone.fetch_add(1, Ordering::SeqCst); async move { println!("[{}] تنفيذ المهمة في: {}", cnt, chrono::Local::now()); // هنا يمكن أن يكون منطق عملك simulate_work().await; } });
println!("تم تشغيل المخطط باستخدام cron."); job.start().await;
// عرض العمل لمدة دقيقتين tokio::time::sleep(Duration::from_secs(120)).await;}
async fn simulate_work() { // محاكاة العمل tokio::time::sleep(Duration::from_millis(500)).await;}مثال 3: مخطط بمهام متعددة وأولويات
استخدام مكتبة async-task-scheduler لإدارة مهام متعددة:
use async_task_scheduler::{Scheduler, Task, Priority};use std::time::Duration;
#[tokio::main]async fn main() { let mut scheduler = Scheduler::new();
// مهمة ذات أولوية عالية — تُنفذ كل ثانيتين scheduler.add_task( Task::new("high_priority_task", || async { println!("[HIGH] تم تنفيذ المهمة العاجلة"); }) .interval(Duration::from_secs(2)) .priority(Priority::High) );
// مهمة ذات أولوية منخفضة — تُنفذ كل 10 ثوانٍ scheduler.add_task( Task::new("low_priority_task", || async { println!("[LOW] تم تنفيذ المهمة منخفضة الأولوية"); }) .interval(Duration::from_secs(10)) .priority(Priority::Low) );
println!("تم تشغيل المخطط بمهام متعددة وأولويات."); scheduler.start().await;
// تشغيل لمدة 30 ثانية tokio::time::sleep(Duration::from_secs(30)).await;}مقارنة مع Python
بينما تقدم Python مكتبات مثل APScheduler و schedule، توفر Rust أداءً أعلى واستهلاكًا أقل للذاكرة. في اختبارات الأداء، كان مخطط Rust أسرع بحوالي 10-15 مرة من نظيره في Python لنفس المهام. ومع ذلك، يتطلب Rust كتابة كود أكثر تعقيدًا قليلاً بسبب إدارة الذاكرة والأنواع.
الخلاصة
اختيار المكتبة يعتمد على احتياجاتك: tokio-schedule مثالي للمشاريع القائمة على tokio، cron للتحكم الدقيق في الوقت، و async-task-scheduler للمهام المعقدة ذات الأولويات. جرب هذه الأمثلة في مشروعك القادم بلغة Rust!