Laravel队列作业上的行为不一致

问题描述 投票:0回答:1

我有一份看起来像这样的工作:

<?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);
    }
}

现在您会注意到我在handle函数中有一个Redis调节器,并且我立即在回调中抛出了一个错误。这就是我正在测试的东西,那个错误就是出问题了。

[您知道,我试图区分LimiterTimeoutExceptions和Throttler回调内部引发的异常。当我通过sync连接运行作业时,一切都会按预期进行:FakeJob::dispatch($user)->onConnection('sync');由于我在上一个请求之后的60秒内发出了一个请求,因此发生了错误,该错误进入了LimiterTimeoutException catch块,并且节气门回调转到failed函数。

但是当我通过默认的调度程序(数据库)调度作业时,似乎每个错误都通过LimiterTimeoutException catch块,直到达到重试限制为止-该错误进入了failed函数,但不是“假异常”错误。

我对此感到非常困惑。

注意:即使我的'假异常'最终被LimiterTimeoutException catch块捕获,但$e->getMessage()函数由于某种原因也不会在那里返回fake exception。但我100%确信是导致该错误的原因,因为这绝对不是由于这些测试中的调节器引起的。

laravel queue jobs
1个回答
0
投票

[好,所以实际上发生的事情是,直到达到重试限制,无论发生什么异常,它都不会在failed()函数中结束。如果我想以不同于其他所有错误的方式处理LimiterTimeoutException错误,则必须将我的Redis::throttle调用包装在try-catch中,然后仅检查catch中的错误类型。

© www.soinside.com 2019 - 2024. All rights reserved.