Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel: How do I make a Redis queued job fail?

Tags:

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');
    }
}
like image 427
stef Avatar asked Jun 11 '18 14:06

stef


People also ask

How do I fail a job in Laravel?

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.

What is the difference between job and queue in Laravel?

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.

What is Redis queue Laravel?

Redis Queue is a python library for queueing purposes for background handling.


1 Answers

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.

like image 168
Marco Aurélio Deleu Avatar answered Oct 11 '22 14:10

Marco Aurélio Deleu