Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel delete job once it fails

Tags:

I have a job that times out and once it fails it dispatches another one just like itself so that it can run infinitely and without overlapping. However the job that fails stays in the queue and gets re-tried so I eventually have more than one job running which breaks the whole purpose.

Here is how I handle the failing of the job:

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() comes from InteractsWithQueue trait. What am I doing wrong?

Edit: I am using horizon for running the jobs, here is the configuration for the custom queue set in config/horizon.php

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

The job that I am dispatching is creating a Thruway client to connect to a web-socket server and subscribe to a channel for updates so I want to run this job forever, but only run one instance of this job at any time. That is why I want it to run once without any tries and once it times out to dispatch another instance that will run and the loop will continue. I couldn't think of a better way to achieve this, is there another way to do this better?

like image 677
PU2014 Avatar asked Jul 04 '19 13:07

PU2014


2 Answers

The reason why failed is not executed, it is only triggered when a job exceeds it's maximum tries. The flow looks something like this.

$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

This logic is changed if your job actually crashes, this example is only when it runs indefinitely. Where the logic is handled.

On your queue definition in config/horizon.php you can define tries.

'my-short-queue' => [
    'connection' => 'redis',
    'queue' => ['my-short-queue'],
    'balance' => 'simple',
    'processes' => 1,
    'tries' => 1,
]
like image 196
mrhn Avatar answered Sep 30 '22 16:09

mrhn


Found you can actually do this in the failed method in a queued job:

/**
 * Handle the failing job.
 *
 * @param Exception $ex
 *
 * @return void
 */
public function failed(Exception $ex)
{
    $this->delete();
}
like image 31
Steve Bauman Avatar answered Sep 30 '22 16:09

Steve Bauman