اذهب إلى المحتوى

السؤال

نشر

لقد قمت بإنشاء رتل queue لإرسال كمية كبيرة من الرسائل الالكترونية للمستخدمين وقمت بتشغيل التطبيق على استضافة مشتركة عن طريق cron بالأمر التالي:

php artisan queue:work

يتم تنفيذ الأمر وإرسال الرسائل ولكن بعدها أحصل على هذا الخطأ وتتوقف العملية عن التكرار:

[ErrorException] 
Invalid argument supplied for foreach()

وعند مراقبة السجل ألاحظ وجود هذا الخطأ:

[2015-04-12 18:59:01] production.ERROR: exception 'ErrorException' with message 'Invalid argument supplied for foreach()' in /home/a109/vendor/symfony/console/Symfony/Component/Console/Input/ArgvInput.php:287 Stack trace:
#0 /home/a109/vendor/symfony/console/Symfony/Component/Console/Input/ArgvInput.php(287): 

كيف أستطيع تفعيل الرتل لإجراء العملية بشكل متكرر على الاستضافة المشتركة دون تكرار الخطأ؟

Recommended Posts

  • 0
نشر

يحدث هذا الخطأ عندما تمرر قيمة null إلى الحلقة، أي بمعنى آخر عند عدم وجود أعمال للقيام بها. وبالتالي يتم التوقف عن إرسال العمليات إلى الرتل ويعطي رسالة الخطأ لعدم وجود أي بيانات لإجراء حلقة التكرار عليها.

يوجد أمر آخر لمنع حدوث ذلك أثناء تشغيل الرتل هو:

php artisan queue:work --stop-when-empty

ويقوم بدوره بإيقاف العمل عند عدم وجود أي عمليات ضمن الرتل.

ولكن هذه الطريقة متبعة فقط للأعمال الصغيرة والتي لا تتطلب الكثير من الوقت. فبفرض تراكم عدد من الأعمال أكبر من 20 مثلاً وسيتم تكراره كل دقيقة، فذلك أيضاً سيسبب خطأ آخر أو تضارب في المعلومات لأن العملية السابقة لم تكن قد انتهت قبل البدء بالعملية التالية وهكذا.

الأسلوب المتبع لحل هذه المشاكل وخاصة عند وجود كمية أكبر من العمليات هو كالتالي:

أولاً نقوم بإنشاء أمر جديد لإرسال الرسائل:

php artisan make:command SendContactEmails

ضمن الملف SendContactEmails.php نقوم بالتغيير التالي:

protected $signature = 'emails:work';

وضمن التابع handle:

return $this->call('queue:work', [
    '--queue' => 'emails', 
    '--stop-when-empty' => null,
]);

ثم ضمن app/Console/Kernal.php نضيف الأمر السابق:

protected $commands = [
    \App\Console\Commands\SendContactEmails::class
];

وأخيراً يتم جدولة الأمر السابق كل دقيقة بالشكل التالي:

protected function schedule(Schedule $schedule)
{
    $schedule->command('emails:work')->everyMinute()->withoutOverlapping();
    
}

حيث سيسمح استخدام withoutOverlapping من تضارب العمليات وانتهاء العملية السابقة قبل البدء بالعملية التي تليها

ويتم بعدها تشغيل cron بالأمر التالي:

* * * * * /usr/local/bin/php /home/username/project/artisan schedule:run > /dev/null 2>&1

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...