الخطوات
-
1
ضبط برنامج تشغيل الطابور
اضبط
QUEUE_CONNECTION=databaseفي ملف.env. ثم أنشئ migration جدول المهام وشغّله. هذا ينشئ جدوليjobsوfailed_jobsحيث ستوجد إدخالات الطابور.bash# .env QUEUE_CONNECTION=database # Generate and run the migrations php artisan queue:table php artisan queue:failed-table php artisan migrate -
2
إنشاء كلاس Job
أنشئ مهمة بـ
make:job. يحصل الكلاس على طريقةhandle()حيث يحدث العمل. أدخل أي اعتماديات مباشرة — حاوية الخدمة تحلها عندما يلتقط العامل المهمة.bashphp artisan make:job SendWelcomeEmail -
3
تنفيذ المهمة
نفّذ
ShouldQueueلإخبار Laravel أن هذه المهمة مُضافة للطابور (لا تزامنية). خزّن فقط ما تحتاجه في المُنشئ — عادةً النموذج أو كائن قيمة صغير. تجنب تخزين مصفوفات كبيرة أو كائنات طلب كاملة؛ فهي تُضخّم حجم المهمة المتسلسلة.php<?php namespace App\Jobs; use App\Mail\WelcomeMail; use App\Models\User; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Mail; class SendWelcomeEmail implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public int $tries = 3; // Retry up to 3 times public int $backoff = 60; // Wait 60s between retries public function __construct( public readonly User $user ) {} public function handle(): void { Mail::to($this->user)->send(new WelcomeMail($this->user)); } public function failed(\Throwable $exception): void { // Notify the team, log, or clean up logger()->error('SendWelcomeEmail failed', [ 'user_id' => $this->user->id, 'error' => $exception->getMessage(), ]); } } -
4
إرسال المهمة إلى الطابور
أرسل من أي مكان — controller أو service أو مستمع لحدث. تُسلسَل المهمة، تُكتب إلى جدول
jobs، ويلتقطها العامل بشكل غير متزامن. استخدمdispatch()للإضافة الفورية أوdispatch()->delay()لجدولتها لاحقاً.phpuse App\Jobs\SendWelcomeEmail; // In a controller after registration SendWelcomeEmail::dispatch($user); // Delay by 5 minutes SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(5)); // Send to a specific queue (useful for prioritisation) SendWelcomeEmail::dispatch($user)->onQueue('emails'); // Dispatch only if condition is met SendWelcomeEmail::dispatchIf($user->wants_email, $user); -
5
تشغيل العامل
العامل يسحب المهام من الطابور وينفذها. استخدم
queue:workفي التطوير. يعالج المهام باستمرار حتى توقفه. للإنتاج استخدم مدير عمليات — Supervisor يضمن إعادة تشغيل العامل تلقائياً عند تعطله.bash# Development php artisan queue:work # Process a specific queue with timeout and memory limit php artisan queue:work --queue=emails,default --timeout=60 --memory=128 # Process a single job then exit (useful in cron-based setups) php artisan queue:work --once -
6
ضبط Supervisor للإنتاج
Supervisor يُبقي عملية العامل تعمل على الخادم. أنشئ ملف ضبط في
/etc/supervisor/conf.d/. إعدادnumprocsيتحكم في عدد عمليات العمال المتوازية — اضبطه بناءً على حجم المهام وموارد الخادم.ini[program:laravel-worker] process_name=%(program_name)s_%(process_num)02d command=php /var/www/esb1995.com/artisan queue:work database --sleep=3 --tries=3 --timeout=90 autostart=true autorestart=true stopasgroup=true killasgroup=true user=apache numprocs=2 redirect_stderr=true stdout_logfile=/var/log/worker.log stopwaitsecs=3600 -
7
مراقبة المهام الفاشلة وإعادة محاولتها
عندما تتجاوز مهمة حد
$tries، تصل إلى جدولfailed_jobs. استخدم أوامر Artisan للفحص وإعادة المحاولة. في الإنتاج، فكر في إعداد تنبيهات عند ازدياد عدد المهام الفاشلة — هذا يعني أن شيئاً ما مكسور في مكان ما.bash# List all failed jobs php artisan queue:failed # Retry a specific failed job by its UUID php artisan queue:retry 5 # Retry all failed jobs php artisan queue:retry all # Delete a specific failed job php artisan queue:forget 5 # Delete all failed jobs php artisan queue:flush -
8
إعادة تشغيل العمال بعد النشر
العمال يحملون كود التطبيق عند البدء. إذا نشرت كوداً جديداً دون إعادة تشغيل العمال، ستستمر العمليات الجارية في استخدام الكود القديم. النمط الآمن هو إشارة إعادة تشغيل بعد كل نشر — ينهي العامل مهمته الحالية ثم يخرج بشكل نظيف ليعيد Supervisor تشغيله بالكود الجديد.
bash# Add this to your deploy script after git pull + optimize php artisan queue:restart # Supervisor will automatically start fresh workers with new code # (queue:restart signals via the cache — ensure your cache driver is shared)
نصائح ومحاذير
- استخدم طوابير مسماة لترتيب الأولويات: <code>--queue=critical,high,default</code>. العامل يُفرغ <code>critical</code> كلياً قبل أن يلمس <code>high</code>. ضع معالجة المدفوعات في <code>critical</code> والبريد الإلكتروني في <code>default</code>.
- اضبط <code>$timeout</code> على كلاس المهمة لإيقاف المهام المعلقة. بدونه، مهمة عالقة تحجز مكان عامل إلى الأبد.
- تجنب تخزين مجموعات Eloquent كاملة في منشئ المهمة. اسحب ما تحتاجه داخل <code>handle()</code> — البيانات قد تكون تغيرت بين الإرسال والتنفيذ.
- <code>queue:work</code> يحمّل تطبيقك مرة واحدة ويبقيه في الذاكرة. تغييرات الكود لا تُلتقط حتى يُعاد تشغيل العامل. شغّل دائماً <code>queue:restart</code> بعد النشر.
- للتطوير المحلي، اضبط <code>QUEUE_CONNECTION=sync</code> في <code>.env</code> — المهام تعمل فوراً دون الحاجة لعامل، مما يجعل التصحيح أسهل بكثير.
خاتمة
الطوابير ليست تحسيناً — بل هي البنية الصحيحة لأي عمل لا يجب أن يعيق الاستجابة. اجعل برنامج تشغيل قاعدة البيانات يعمل محلياً، ثم انتقل إلى Redis في الإنتاج لأداء أفضل.