Это продолжение Laravel - последовательное выполнение заданий
Я решил пойти с ограничением скорости Redis. Код ниже
jobClass {
protected $subscription;
public function __construct(Subscription$subscription) {
$this->subscription= $subscription;
}
public function handle() {
Redis::funnel('mailingJob')->limit(1)->then(function () {
// Job logic...
(new Mailer($this->subscription))->send();
}, function () {
// Could not obtain lock...
return $this->release(10);
});
}
}
А код контроллера выглядит так.
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Subscriptions;
class MailController extends Controller
{
public function sendEmail() {
Subscriptions::all()
->each(function($subscription) {
SendMailJob::dispatch($subscription);
});
}
}
Теперь, когда я запускаю очередь, некоторые из них работают, остальные (около 90%) не работают с ошибкой ниже в горизонте.
SendMailJob has been attempted too many times or run too long. The job may have previously timed out.
Что мне не хватает? Пожалуйста, направьте меня в правильном направлении.
Моя цель - одновременно запускать только одно задание одного типа.
[...] has been attempted too many times or run too long
- это ошибка, которая не сообщает вам, почему задание не выполнено. Это означает, что какое-то другое исключение приводил к сбою вашего задания каждый раз, когда он выполнялся рабочим, и рабочий пытался его максимальное количество раз, которое позволяла ваша конфигурация. Чтобы понять, почему это не удается, проверьте файл laravel.log на предмет исключения, которое привело к сбою задания.
В вашем случае, поскольку Mailer
связывается с внешней системой, возможно, система, к которой вы подключаетесь, ограничивает вашу скорость, или у них могут быть временные проблемы с подключением или другие простои службы. Опять же, в ваших файлах журнала должно быть больше подробностей.
У Документация Laravel есть подсказка по этому поводу:
When using rate limiting, the number of attempts your job will need to run successfully can be hard to determine. Therefore, it is useful to combine rate limiting with time based attempts.
Суть проблемы в том, что задание продолжает терпеть неудачу до тех пор, пока не будет заблокировано и запущено.
Итак, я полагаю, что там, где вы запускаете своего обработчика очереди, вы не устанавливаете достаточно высокий флаг --tries
.
Хотя вы могли бы просто установить очень высокий --tries
, на самом деле он не масштабируется.
Лучшим решением, как предлагается в документации, было бы увеличение количества попыток, а также использование попытки по времени
Вы также можете увеличить время выпуска return $this->release(10);
здесь. Это должно заставить задание ждать дольше, прежде чем пытаться повторно захватить блокировку, так что будет израсходовано меньше попыток!
Без опции --tries
нет ограничения на количество попыток
@TravisBritz, я не был уверен в этом. Обновлю ответ, спасибо!
Попробуйте это решение.