【发布时间】:2020-01-15 16:41:51
【问题描述】:
我的工作是这样的:
<?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 限制器,并且我立即在回调中抛出了一个错误。这就是我正在测试的内容,而那个错误就是问题所在。
你看,我试图区分 LimiterTimeoutExceptions 和 Throttler 回调中抛出的异常。当我通过sync 连接运行作业时,一切都按预期工作:FakeJob::dispatch($user)->onConnection('sync'); 因为我在前一个请求的 60 秒内发出请求而发生的错误进入 LimiterTimeoutException catch 块,并且在油门回调转到failed函数。
但是当我通过我的默认调度程序(即数据库)安排作业时,似乎每个错误都通过LimiterTimeoutException catch 块,直到我达到重试限制 - 该错误进入failed 函数,但不是“假异常”错误。
我对此感到非常困惑。
注意:即使我的“假异常”最终被LimiterTimeoutException catch 块捕获,$e->getMessage() 函数也不会因为某种原因返回fake exception。但我 100% 确定是那个错误导致它到达那里,因为这绝对不是由于这些测试中的节流阀造成的。
【问题讨论】: