У меня есть задание, которое выглядит следующим образом:
<?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, потому что это определенно не связано с троттлером в этих тестах.