Задание в очереди застряло, возможно, стол заблокирован в Laravel - PullRequest
0 голосов
/ 21 февраля 2019

Я использую очереди для отправки уведомлений по электронной почте в моем приложении Laravel.Я использую базу данных в качестве драйвера очереди, поэтому есть таблица jobs DB, которая выглядит примерно так:

id | queue | payload | attempts | reserved_at

Теперь у меня есть куча неотправленных сообщений в очереди, но это первое, чтовызывая все проблемы: у него есть 255 в столбце attempts, и когда я пытаюсь удалить строку в phpMyAdmin, ничего не происходит - он зависает около 30 секунд, затем выдает пустой экран.

После того, как яперезапустил MySQL, он позволил мне удалить строку, и все остальные сообщения были отправлены правильно.

Содержимое строки (я внимательно посмотрел в поле payload), на поверхности, такое же, как и всеостальные строки.

Это задание, которое выполняется:

public function handle()
{
    try {

        $this->order->sendOrderConfirmation();

    } catch( Exception $e ){

        Log::info('Unable to dispatch order confirmation email.', [
            'order'   => $this->order->id,
            'message' => $e->getMessage(),
            'code'    => $e->getCode(),
            'line'    => $e->getLine(),
            'file'    => $e->getFile()
        ]);

        $this->release();
    }
}

Приведенное выше сообщение журнала нигде не встречается в журналах, но в журналах я нашел следующее:this:

SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'attempts' at row 1 (SQL: update `jobs` set `reserved_at` = 1550737859, `attempts` = 256 where `id` = 1638) in /home/truvisi3/public_html/secure/vendor/laravel/framework/src/Illuminate/Database/Connection.php:647

Похоже, что он пытается увеличить счетчик попыток, но поле ограничено 255. Хорошо, но почему это нарушает всю очередь, а не только этот процесс?И что я могу сделать, чтобы не допустить этого в будущем (помимо ручного изменения формата столбца попыток для приема больших чисел)?

РЕДАКТИРОВАТЬ: вот класс задания

class DispatchOrderConfirmationEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * @var Order
     */
    protected $order;
    public $tries = 10;

    /**
     * Create a new job instance.
     *
     * @param Order $order
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        try {

            $this->order->sendOrderConfirmation();

        } catch( Exception $e ){

            $this->release();
        }
    }
}

1 Ответ

0 голосов
/ 22 февраля 2019

Вам необходимо определить максимальное количество попыток для задания в очереди, в противном случае оно будет выполняться бесконечно.При использовании драйвера database это означает, что число попыток может превысить максимальное значение для поля MySQL TINYINT UNSIGNED, в результате чего исключение базы данных будет выдано при 256-й попытке.

Есть два способа сделатьthis.

Использование --tries при запуске рабочего процесса:

$ php artisan queue:work --tries=10

Или определить свойство $tries для вашего класса заданий:

public $tries = 10;

Когда обасуществует, свойство $tries имеет приоритет.

Рекомендуется всегда указывать максимальное количество попыток для вашего рабочего процесса, используя --tries, чтобы слушатели в очереди, почта и все остальное, использующее ваши очереди, в конечном итоге потерпели неудачупосле слишком большого количества попыток и используйте свойство $tries, чтобы переопределить ограничение, если оно имеет смысл для конкретной работы.

Причина, по которой ваше пользовательское сообщение об ошибке не отображается в журналах, заключается в том, что databaseдрайвер очереди обновляет поля attempts и reserved_at, когда извлекает задание из очереди, а , а затем отправляет задание в рабочий класс.Поскольку приращение attempts вызывает исключение необработанной базы данных перед запуском работника, ваш код никогда не вызывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...