我有一个超时的工作,一旦失败,它会像自己一样分派另一个工作,以便它可以无限运行且不会重叠。但是,失败的工作留在队列中,并被重试,因此我最终要运行多个工作,这破坏了整个目的。
这是我处理工作失败的方法:
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客户端以连接到网络套接字服务器并订阅更新频道,因此我想永远运行此工作,但在任何时候都只能运行该工作的一个实例。这就是为什么我希望它运行一次而不进行任何尝试,并且一旦超时就调度另一个将运行的实例,并且循环将继续。我想不出一种更好的方法来实现这一目标,还有另一种方法可以更好地实现这一目标吗?
答案 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 / horizon.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();
}