Laravel一旦失败就删除作业

时间:2019-07-04 13:31:55

标签: php laravel redis laravel-queue laravel-jobs

我有一个超时的工作,一旦失败,它会像自己一样分派另一个工作,以便它可以无限运行且不会重叠。但是,失败的工作留在队列中,并被重试,因此我最终要运行多个工作,这破坏了整个目的。

这是我处理工作失败的方法:

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特性。我在做什么错了?

编辑: 我使用地平线来运行作业,这是在config/horizon.php

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

我正在分派的工作是创建一个Thruway客户端以连接到网络套接字服务器并订阅更新频道,因此我想永远运行此工作,但在任何时候都只能运行该工作的一个实例。这就是为什么我希望它运行一次而不进行任何尝试,并且一旦超时就调度另一个将运行的实例,并且循环将继续。我想不出一种更好的方法来实现这一目标,还有另一种方法可以更好地实现这一目标吗?

3 个答案:

答案 0 :(得分:1)

失败的原因未执行,仅当作业超过最大尝试次数时才触发。流程看起来像这样。

$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 / horizo​​n.php中的队列定义上,您可以定义尝试。

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

答案 1 :(得分:0)

原来我的工作没有失败,所以failed()方法没有得到执行。即使您在tries => 1文件中将尝试设置为config/horizon.php,也需要在retry_after文件中将0值设置为config/queue.php,以使作业失败就在它超时之后。这样,您的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,
],

答案 2 :(得分:0)

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

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