Непоследовательное поведение в Laravel задании очереди - PullRequest
0 голосов
/ 15 января 2020

У меня есть задание, которое выглядит следующим образом:

<?php

namespace App\Jobs;

use App\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\Redis;

class FakeJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    /**  @var User */
    private $user;
    public $tries = 30;

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

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        try {
            Redis::throttle('key')->allow(1)->every(60)->then(function () {
                // Job logic...
                throw new \Exception('fake exception');
                $this->logInfo($this->user->name);
            });
        } catch(\Illuminate\Contracts\Redis\LimiterTimeoutException $e) {
            $this->logInfo('inside LimiterTimeout catch, ' . $e->getMessage());
            $this->release(1);
        }
    }

    public function failed(\Exception $exception) {
        // Send user notification of failure, etc...
        $this->logInfo('inside failure, ' . $exception->getMessage());
    }

    public function logInfo($message) {
        $path = storage_path('logs/FakeJob.log');
        $logText = time() . ' ' . $message;
        file_put_contents($path, $logText.PHP_EOL , FILE_APPEND | LOCK_EX);
    }
}

Теперь вы заметите, что у меня есть регулятор Redis в функции дескриптора, и что я немедленно выбрасываю ошибку в обратном вызове. Это то, что я тестирую, и эта ошибка - то, что идет не так.

Видите ли, я пытаюсь различить guish между LimiterTimeoutException и исключениями, генерируемыми внутри обратного вызова Throttler. Когда я запускаю задание через соединение sync, все работает должным образом: FakeJob::dispatch($user)->onConnection('sync'); Ошибки, возникающие из-за того, что я сделал запрос в течение 60 секунд после предыдущего запроса go в блок перехвата LimiterTimeoutException, и ошибки, которые происходят внутри обратного вызова Throttle go к функции failed.

Но когда я планирую задание с помощью моего планировщика по умолчанию, который является базой данных, кажется, что КАЖДАЯ ошибка проходит через блок перехвата LimiterTimeoutException До тех пор, пока я не достигну предела повторных попыток - эта ошибка входит в функцию failed, но не в ошибку «поддельное исключение».

Я очень смущен этим.

Обратите внимание: даже если мое «фальшивое исключение» в конечном итоге перехватывается блоком LimiterTimeoutException catch, функция $e->getMessage() НЕ возвращает туда fake exception по какой-то причине. Но я на 100% уверен, что именно эта ошибка приводит к go, потому что это определенно не связано с троттлером в этих тестах.

1 Ответ

0 голосов
/ 16 января 2020

ОК, так что на самом деле происходит то, что в функцию failed() она не попадет, пока не достигнет предела повторных попыток, несмотря ни на что, независимо от того, было ли выброшено исключение. Если я хочу работать с ошибками LimiterTimeoutException иначе, чем с любой другой ошибкой, мне придется заключить мой вызов Redis::throttle в try-catch и просто проверить тип ошибки в catch.

...