【问题标题】:Laravel: How can a queued job move itself to failed_jobs on fail?Laravel:排队的作业如何在失败时将自己移动到 failed_jobs?
【发布时间】:2018-06-27 09:16:52
【问题描述】:

我有一个创建新用户的可排队作业...

<?php

namespace App\Jobs;

...

class CreateNewUser implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /** @var array */
    public $newUserData;

    public function __construct($newUserData)
    {
        $this->newUserData = $newUserData;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $email = $this->newUserData['email'];
        if (User::whereEmail($email)->count()) {
            // TODO: Make this job fail immediately
            throw new UserWithEmailExistsException('User with email ' . $email . ' already exists');
        }

        ...
    }
}

这是一个排队的工作,因为我们批量处理 CSV 以一次加载多个用户,每个用户都需要 2 个表中的条目以及角色和权限表中的多个条目。同步太慢了。

我在handle() 方法的开头检查了是否尚未创建具有相同电子邮件地址的用户(因为可能会有多个作业排队以创建具有相同电子邮件的用户) 如果确实如此,它会抛出一个自定义异常。

如果检查失败,我不希望队列工作人员再次尝试这项工作,因为我知道它会无限期地继续失败,再次尝试是浪费时间。 如何手动强制此作业一劳永逸地失败并移至失败的作业表?

附:我找到了关于 fail() 助手和 $this-&gt;markAsFailed() 方法的 SO 答案,但这些仍然不会立即将作业从作业转移到 failed_jobs。

【问题讨论】:

  • 如果已经存在具有特定电子邮件的用户,您是否有理由要求作业特别失败?如果用户存在,将作业标记为完成是否不够,因为从技术上讲,当您添加已添加的用户时,作业已完成..
  • 好点。您围绕如何解释“失败”提出了一个有趣的讨论。代码没有失败,任务失败了。 CSV 数据中的错误可能导致 2 个不同的用户拥有相同的电子邮件地址。管理员在注册时复制和粘贴错误。我希望被举报。现在我想起来了,我想这项工作应该被称为“AttemptToInsertNewUser()”,可能的成功结果是 A) 创建用户或 B) 在某个报告面板上报告重复。
  • 是的,我认为这似乎更合适。记录重复错误,但是,继续似乎是正确的逻辑。希望你能解决你的问题:)

标签: laravel laravel-5


【解决方案1】:

我已经为你完全重写了我的答案。昨晚我很着急,以为我有一个快速解决您问题的方法,对于错误信息,我深表歉意。

您可以执行以下代码之类的操作,这不会将作业放入失败的作业表中,但会阻止重新尝试的发生。我希望这会有所帮助。

<?php

namespace App\Jobs;

use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class TestJob extends Job implements ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        if ($this->attempts() > 0) {
            // Will not reattempt this job.
            return;
        }

        throw new \Exception('Job will fail.');
    }
}

【讨论】:

  • 该任务不仅仅是检查重复项,因此以后的代码可能会因其他原因而失败,这意味着我希望它重试。
  • @MartinJoiner 如果您不想重试,那么您可以简单地设置$tries = 0;,因此它会在遇到异常时停止。希望对您有所帮助。
  • 不,不会的。尝试次数是在保存在数据库中的类的序列化版本上设置的。即时更改此设置不会更新该类的序列化版本。请先测试您的建议,然后再将它们发布到 stackoverflow。
猜你喜欢
  • 1970-01-01
  • 2020-11-04
  • 2014-11-19
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-16
相关资源
最近更新 更多