Php Laravel在作业失败时删除作业
我有一个超时的工作,一旦它失败,它就会分派另一个和它一样的工作,这样它就可以无限地运行,而不会重叠。然而,失败的作业会留在队列中并重新尝试,因此我最终会运行多个作业,这破坏了整个目的 以下是我如何处理工作失败的原因:Php Laravel在作业失败时删除作业,php,laravel,redis,laravel-queue,laravel-jobs,Php,Laravel,Redis,Laravel Queue,Laravel Jobs,我有一个超时的工作,一旦它失败,它就会分派另一个和它一样的工作,这样它就可以无限地运行,而不会重叠。然而,失败的作业会留在队列中并重新尝试,因此我最终会运行多个作业,这破坏了整个目的 以下是我如何处理工作失败的原因: use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function handle() { //infinite websocket listening loop } pub
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()
来自interacticswithqueue
trait。我做错了什么
编辑:
我使用horizon来运行作业,下面是在config/horizon.php
'supervisor-long' => [
'connection' => 'redis-long',
'queue' => ['long-queue'],
'balance' => 'simple',
'processes' => 3,
'tries' => 1,
'timeout' => 3600,
],
我正在调度的作业正在创建一个Throuway客户端,用于连接到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
如果您的作业实际崩溃,则此逻辑会发生更改,此示例仅适用于无限期运行的情况。逻辑在哪里
在config/horizon.php中的队列定义中,可以定义尝试
'my-short-queue' => [
'connection' => 'redis',
'queue' => ['my-short-queue'],
'balance' => 'simple',
'processes' => 1,
'tries' => 1,
]
原来我的作业没有失败,因此没有执行
failed()
方法。即使在config/horizon.php
文件中设置了trytes totrytes=>1
,也需要在config/queue.php
文件中将retry\u after
值设置为0
,以便作业在超时后立即失败。这样,您的failed()
方法将立即被调用。下面是我的配置文件的最终形式
config/queue.php
:
'redis-long' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => 'long-queue',
'retry_after' => 0,
'block_for' => null,
],
'supervisor-long' => [
'connection' => 'redis-long',
'queue' => ['long-queue'],
'balance' => 'simple',
'processes' => 1,
'tries' => 1,
'timeout' => 3600,
],
config/horizon.php
:
'redis-long' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => 'long-queue',
'retry_after' => 0,
'block_for' => null,
],
'supervisor-long' => [
'connection' => 'redis-long',
'queue' => ['long-queue'],
'balance' => 'simple',
'processes' => 1,
'tries' => 1,
'timeout' => 3600,
],
发现您实际上可以在排队作业中的
失败的方法中执行此操作:
/**
* Handle the failing job.
*
* @param Exception $ex
*
* @return void
*/
public function failed(Exception $ex)
{
$this->delete();
}
为什么在失败的函数中再次分派作业?我假设在第一次尝试之后,您希望将作业移动到另一个队列(长队列)。作业仍在默认队列上运行,因为您未设置最大尝试次数。您可以更改队列命令,如sophp artisan queue:work--trytes=1
,在第一次尝试之后,您的作业将被移动到failed_jobs表。您尝试执行的操作与Laravel已经执行的操作之间有什么区别?所有这些注释的总和,使用内置重试功能有什么问题?@MartinHenriksen有时您可能希望将失败的作业移动到另一个队列,例如延迟或更长时间的队列。因此,您可以选择解决方案来限制重试次数,Milena的评论在那里非常有效。我使用laravel horizon来处理队列,因此,Milena的解决方案不适用通常标准是将retry_after设置为超过超时时间,以便确保作业有机会执行。我不确定在0之后重试是否是一个好主意。我不希望作业在任何时候重试,并且不设置retry\u after=>0
会给整个过程增加延迟,该延迟必须通过,直到调用failed()
函数为止。此配置产生所需的行为。