Laravel 尝试排队作业,触发新尝试的正确方法?

Posted

技术标签:

【中文标题】Laravel 尝试排队作业,触发新尝试的正确方法?【英文标题】:Laravel queue jobs with attempts, correct way to trigger new attempt? 【发布时间】:2020-03-11 10:04:49 【问题描述】:

我正在尝试找出正确的方法。

public $tries = 10;

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
    $result_of_some_logic = false;
    if($result_of_some_logic)
        // for the purpose of this example, we're all done here.
     else
        // we need to retry 10 minutes from now. how to trigger this attempt, and this attempt only!, to fail? 
    

我阅读了 laravel 文档,但我不清楚正确的方法是什么。我注意到,如果我创建了一个 php 错误(例如 throw new whatisnotdeclaredinnamespace()),则作业尝试将失败,工作人员将重试直到超过 $tries 的数量。这几乎是我想要的行为,但我显然想要一个干净的代码解决方案。

总结一下:在 Laravel 5.8 中,在 handle() 函数中“标记”尝试失败的正确方法是什么?

【问题讨论】:

你能解释一下为什么你不想使用异常吗? 因为它会导致 laravel 日志中出现大量堆栈跟踪日志,而大多数时候“异常”只是第三方要求我等待我可以向他们的 API 提交另一个请求。我想优雅地看到尝试次数上升,直到最大尝试次数过去,然后升级为异常并让 failed() 方法检索异常消息并发送通知电子邮件。 【参考方案1】:

您可以尝试延迟将作业释放回队列:

$this->release($delayInSeconds);

【讨论】:

这需要我手动测试尝试次数是否 >= $tries 来决定我应该释放()还是抛出异常。这感觉就像是根据 laravel 的原则进行编码。但我是 Laravel 的新手,所以也许我只是看不清楚。 如果达到尝试限制,它已经失败了【参考方案2】:

为什么不使用 failed 函数来处理您的错误?

https://laravel.com/docs/5.8/queues#dealing-with-failed-jobs

<?php

namespace App\Jobs;

use Exception;
use App\Podcast;
use App\AudioProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class ProcessPodcast implements ShouldQueue

    use InteractsWithQueue, Queueable, SerializesModels;

    protected $podcast;

    /**
     * Create a new job instance.
     *
     * @param  Podcast  $podcast
     * @return void
     */
    public function __construct(Podcast $podcast)
    
        $this->podcast = $podcast;
    

    /**
     * Execute the job.
     *
     * @param  AudioProcessor  $processor
     * @return void
     */
    public function handle(AudioProcessor $processor)
    
        // Process uploaded podcast...
    

    /**
     * The job failed to process.
     *
     * @param  Exception  $exception
     * @return void
     */
    public function failed(Exception $exception)
    
        // Send user notification of failure, etc...
    

【讨论】:

我确实使用了失败的方法,但我想知道如何优雅地使 handle() 方法导致重新尝试。现在我使用 throw new \Exception('lorem ipsum...'),每次尝试都会生成大量日志文件行。我想限制这一点。 我看到的唯一方法是再次调度作业(在当前作业中)而不是抛出异常。如果您对日志空间有疑问,您应该只为作业配置日志记录,例如。通过为队列制作特定的 .env。

以上是关于Laravel 尝试排队作业,触发新尝试的正确方法?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 嵌套作业

Laravel 排队事件侦听器与作业之间的区别

Laravel - 自动执行排队的作业[重复]

Laravel 排队的作业即使有延迟也会立即处理

如何使用 Laravel 5.1 在 IronMQ 中获取排队作业的数量?

laravel 5.1 在没有 VM 重启的情况下看不到作业文件的更改