ما هي مكتبة Bull ولماذا تحتاجها؟
Bull هي مكتبة قوية وشائعة لإدارة قوائم المهام (job queues) في بيئة Node.js. تم بناؤها فوق Redis وتوفر طريقة موثوقة وقابلة للتوسع ومرنة لمعالجة المهام الخلفية. إذا كان تطبيقك يحتاج إلى تنفيذ عمليات لا يجب أن تعيق التدفق الرئيسي (مثل إرسال البريد الإلكتروني، معالجة الصور، إنشاء PDF، المزامنة مع واجهات API الخارجية، تحليل البيانات)، فإن Bull هو الحل الأمثل.
لماذا تستخدم Bull؟
- معالجة غير متزامنة: تخفف العبء عن الخادم الرئيسي بنقل المهام الثقيلة إلى عمليات خلفية.
- الموثوقية: تُخزَّن المهام في Redis، لذا لا تُفقد عند إعادة تشغيل التطبيق أو تعطل العامل (worker).
- إعادة المحاولة: دعم مدمج لإعادة المحاولة التلقائية عند حدوث أخطاء.
- الجدولة: إمكانية تأجيل المهام أو تشغيلها وفق جدول زمني (cron).
- الأولويات: التحكم في ترتيب تنفيذ المهام.
- المراقبة: تتبع حالة قوائم المهام بسهولة باستخدام واجهة المستخدم المدمجة (Bull Board).
تثبيت Bull
للبدء، تأكد من تثبيت وتشغيل Redis. Bull لا يعمل بدونه.
- تثبيت Redis (مثال لأوبونتو/ديبيان):
sudo apt update sudo apt install redis-server sudo systemctl start redis - تثبيت Bull عبر npm:
npm install bull - تثبيت Bull Board (اختياري، للواجهة الرسومية):
npm install @bull-board/express @bull-board/api
بداية سريعة: المثال الأول
لننشئ قائمة مهام بسيطة لإرسال رسائل البريد الإلكتروني الترحيبية.
الخطوة 1: إنشاء المنتج (producer.js)
const Queue = require('bull');
// إنشاء قائمة مهام باسم 'emailQueue'
const emailQueue = new Queue('emailQueue', {
redis: { host: 'localhost', port: 6379 }
});
// دالة لإضافة مهمة إلى القائمة
async function addEmailJob(to, subject, body) {
const job = await emailQueue.add(
{ to, subject, body }, // بيانات المهمة
{
attempts: 3, // عدد محاولات إعادة المحاولة عند الخطأ
backoff: { type: 'fixed', delay: 5000 } // تأخير بين المحاولات (5 ثوانٍ)
}
);
console.log(`تمت إضافة المهمة بالرقم: ${job.id}`);
return job;
}
// مثال استخدام
addEmailJob('user@example.com', 'مرحباً بك!', 'شكراً لتسجيلك.')
.then(() => process.exit(0))
.catch(err => console.error(err));
الخطوة 2: إنشاء العامل (worker.js)
const Queue = require('bull');
// الاتصال بنفس قائمة المهام
const emailQueue = new Queue('emailQueue', {
redis: { host: 'localhost', port: 6379 }
});
// معالج المهام
emailQueue.process(async (job) => {
console.log(`جارٍ معالجة المهمة ${job.id}...`);
const { to, subject, body } = job.data;
// محاكاة إرسال البريد الإلكتروني (في الواقع استخدم nodemailer)
await new Promise(resolve => setTimeout(resolve, 2000));
console.log(`تم إرسال البريد الإلكتروني إلى ${to}: ${subject}`);
// إذا حدث خطأ، قم بإلقاء خطأ
// throw new Error('خطأ في الإرسال');
});
console.log('العامل قيد التشغيل وينتظر المهام...');
الخطوة 3: التشغيل
قم أولاً بتشغيل العامل: node worker.js. ثم في نافذة طرفية أخرى، قم بتشغيل المنتج: node producer.js. ستلاحظ كيف تدخل المهمة إلى قائمة الانتظار وتُعالج.
الطرق الأساسية في Bull
1. new Queue(name, [options]) — إنشاء قائمة مهام
الوظيفة: إنشاء نسخة جديدة من قائمة المهام. إذا كانت قائمة مهام بنفس الاسم موجودة بالفعل في Redis، فإنها تتصل بها.