Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Laravel在作业失败时删除作业_Php_Laravel_Redis_Laravel Queue_Laravel Jobs - Fatal编程技术网

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 to
trytes=>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();
}

为什么在失败的函数中再次分派作业?我假设在第一次尝试之后,您希望将作业移动到另一个队列(长队列)。作业仍在默认队列上运行,因为您未设置最大尝试次数。您可以更改队列命令,如so
php artisan queue:work--trytes=1
,在第一次尝试之后,您的作业将被移动到failed_jobs表。您尝试执行的操作与Laravel已经执行的操作之间有什么区别?所有这些注释的总和,使用内置重试功能有什么问题?@MartinHenriksen有时您可能希望将失败的作业移动到另一个队列,例如延迟或更长时间的队列。因此,您可以选择解决方案来限制重试次数,Milena的评论在那里非常有效。我使用laravel horizon来处理队列,因此,Milena的解决方案不适用通常标准是将retry_after设置为超过超时时间,以便确保作业有机会执行。我不确定在0之后重试是否是一个好主意。我不希望作业在任何时候重试,并且不设置
retry\u after=>0
会给整个过程增加延迟,该延迟必须通过,直到调用
failed()
函数为止。此配置产生所需的行为。