Laravel 一旦失败就删除作业

Laravel delete job once it fails

我有一份工作会超时,一旦它失败,它就会像它自己一样调度另一个工作,这样它就可以 运行 无限且不重叠。然而,失败的工作留在队列中并重新尝试,所以我最终有不止一份工作 运行ning 打破了整个目的。

以下是我处理作业失败的方式:

use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

public function handle()
{
    //infinite websocket listening loop
}

public function failed(Exception $exception)
{
    $this::dispatch()->onQueue('long-queue');
    $this->delete();
}

$this->delete() 来自 InteractsWithQueue 特质。我做错了什么?

编辑: 我正在使用 horizo​​n 来处理 运行 作业,这里是 config/horizon.php

中设置的自定义队列的配置
'supervisor-long' => [
    'connection' => 'redis-long',
    'queue' => ['long-queue'],
    'balance' => 'simple',
    'processes' => 3,
    'tries' => 1,
    'timeout' => 3600,
],

我正在分派的工作是创建一个 Thruway 客户端以连接到 Web 套接字服务器并订阅一个频道以获取更新,所以我想永远 运行 这个工作,但只有 运行 此作业的一个实例随时可用。这就是为什么我希望它在没有任何尝试的情况下 运行 一次,一旦它超时调度另一个将 运行 并且循环将继续的实例。我想不出更好的方法来实现这一点,还有其他更好的方法吗?

失败不执行的原因,只有在作业超过最大尝试次数时才会触发。流程看起来像这样。

$job->dispatch(); // try 1
// times out
// retries on try 2 now
// times out
// retries on try 3 now
// max attempt is hit and MaxAttempt exception is thrown
// failed is called

如果你的作业真的崩溃了,这个逻辑就会改变,这个例子只是在它无限期运行的时候。逻辑是 handled.

在 config/horizon 中的队列定义中。php 您可以定义尝试。

'my-short-queue' => [
    'connection' => 'redis',
    'queue' => ['my-short-queue'],
    'balance' => 'simple',
    'processes' => 1,
    'tries' => 1,
]

原来我的作业没有失败,所以 failed() 方法没有被执行。即使您在 config/horizon.php 文件中将尝试设置为 tries => 1,您也需要在 config/queue.php 文件中将 retry_after 值设置为 0,以便作业失败就在它超时之后。这样您的 failed() 方法就会立即被调用。您可以在下面找到我的配置文件的最终形式。

config/queue.php:

'redis-long' => [
    'driver' => 'redis',
    'connection' => 'default',
    'queue' => 'long-queue',
    'retry_after' => 0,
    'block_for' => null,
],

config/horizon.php:

'supervisor-long' => [
    'connection' => 'redis-long',
    'queue' => ['long-queue'],
    'balance' => 'simple',
    'processes' => 1,
    'tries' => 1,
    'timeout' => 3600,
],

发现您实际上可以在排队作业的 failed 方法中执行此操作:

/**
 * Handle the failing job.
 *
 * @param Exception $ex
 *
 * @return void
 */
public function failed(Exception $ex)
{
    $this->delete();
}