In Laravel while running Redis queues, I'm unable to get the failed
method called in my Job class. I want to make sure I can properly log them and that they are written to the failed_jobs table.
Laravel documentation about queues states
You may define a failed method directly on your job class, allowing you to perform job specific clean-up when a failure occurs. This is the perfect location to send an alert to your users or revert any actions performed by the job. The Exception that caused the job to fail will be passed to the failed method:
I'm not 100% sure what Laravel consider to be "the exception that caused the job to fail". Below is a very simple job class. All that's appearing in my logs is It did not work
and exception caught
.
I'm launching this queue with the following command, specifically setting tries
to 1 so it doesn't attempt to re-run the job.
php artisan queue:work redis --queue=widgets --tries=1
How can I get the failed method to be called and the job to appear in the failed_jobs table?
<?php
namespace App\Jobs;
use Exception;
use App\Processors\WidgetProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class WidgetJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct($widget)
{
$this->widget = $widget;
}
public function handle(WidgetProcessor $processor)
{
Redis::throttle('WidgetJob')->allow(5)->every(60)->then(function () use ($processor) {
try {
$var = false;
if($var == false) {
Log::notice('It did not work');
throw new Exception;
} else {
Log::notice('It worked');
}
} catch(Exception $e) {
Log::notice('Exception caught');
}
}, function () {
return $this->release(5);
});
}
public function failed(Exception $exception)
{
Log::notice('failed was called');
}
}
Use the InteractsWithQueue trait and call either delete() if you want to delete the job, or fail($exception = null) if you want to fail it. Failing the job means it will be deleted, logged into the failed_jobs table and the JobFailed event is triggered.
Jobs and QueuesThe line itself is the Queue, and each customer in the line is a Job. In order to process Jobs in the Queue you need command line processes or daemons. Think of launching a queue daemon on the command line as adding a new bank teller to the pool of available bank tellers.
Redis Queue is a python library for queueing purposes for background handling.
Laravel Queue system works as a daemon that picks up jobs, runs them and moves on. If your job never throws exception, Laravel will consider it as a successful job. The problem in your snippet is this:
try {
...
} catch(Exception $e) {
Log::notice('Exception caught');
}
By catching the exception, you don't let Laravel mark this job as failed.
You have two choices here: Either don't use try...catch
or, if you really want to use it, re-throw the exception as follows:
try {
...
} catch(Exception $e) {
Log::notice('Exception caught');
throw $e;
}
By letting the exception bubble up, Laravel will fail the job and invoke your failed()
routine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With