Release job back to queue and fail a Laravel Job

How to release a job manually to the queue for reprocessing later or manually fail a job whenever you want.

Table of Content

  1. Releasing job back to the queue
  2. Releasing job back to queue after given time
  3. Manually fail a job

Setup initial project

Setup a fresh Laravel web application. Then create a job class called ProcessData using below artisan command.

php artisan make:job ProcessData

Dispatch above created job class.

use App\Jobs\ProcessData;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    //Log request
    Log::info("Received a get request on root route");
    ProcessData::dispatch();
    
});

Run Laravel application.

php artisan serve

Run a queue worker

php artisan queue:work

Releasing job back to the queue

You can release job back to queue if anything goes wrong like

  1. External resource not available.
  2. Due to an Incomplete process.
  3. Due to unhandled exceptions.

Please note that using $tihs->release() does not exit the job and put back to queue. It will execute rest of the code if available before releasing back to queue. According to below example, code line after release() method will execute. Therefore pay attention to where you want to hold further execution of the job and release it back to the queue. You can use release() method with return, try catch, or if else to quickly sent that job back to queue without further execution of the job.

     public function handle(): void
        {
            Log::info('Processing...  Process Data Job');
            $this->release();
            Log::info("Done Processing Process Data Job");
        }

    Check logs. You will see code line after release() method had executed.

    [2025-01-01 07:02:44] local.INFO: Received a get request on root route  
    [2025-01-01 07:02:47] local.INFO: Processing... Data Job  
    [2025-01-01 07:02:47] local.INFO: Done Processing Data Job  
    [2025-01-01 07:02:48] local.INFO: Processing... Data Job  
    [2025-01-01 07:02:48] local.INFO: Done Processing Data Job  
    [2025-01-01 07:02:48] local.INFO: Processing... Data Job  
    [2025-01-01 07:02:48] local.INFO: Done Processing Image Data Job 

    Example 1: using Release() method

    Open ProcessData job class add below code.

    1. Log information on the handle() method.
    2. Use release() method to release job back to the queue.
    3. Add 3 attempts to job class.
    <?php
    
    namespace App\Jobs;
    
    use Illuminate\Contracts\Queue\ShouldQueue;
    use Illuminate\Foundation\Queue\Queueable;
    use Illuminate\Support\Facades\Log;
    
    class ProcessData implements ShouldQueue
    {
        use Queueable;
    
        public $tries = 3;
    
        public function __construct(){}
    
        /**
         * Execute the job.
         */
        public function handle(): void
        {
            Log::info('Processing... Data Job');
            if(true){
                $this->release();
                return;
            }
            Log::info('Done... Data Job');
        }
    }

    Make sure to rerun the queue worker before testing.

    php artisan queue:work

    Check Laravel logs.

    Job was released back to queue till it max out the retry attempts.

    [2025-01-01 07:16:58] local.INFO: Received a get request on root route  
    [2025-01-01 07:17:00] local.INFO: Processing... Data Job  
    [2025-01-01 07:17:00] local.INFO: Processing... Data Job  
    [2025-01-01 07:17:01] local.INFO: Processing... Data Job  
    [2025-01-01 07:17:02] local.ERROR: App\Jobs\ProcessData has been attempted too many times. 

    Releasing job back to queue after given time

    Only argument of the release() method accept the delay. You can pass integer value in seconds or date time interface.

    
    //Integer value in seconds
    $this->release(10)
    
    //Using now()
    $this->release(now()->addSeconds(5));

    Manually failing a job

    Falling a job mean it will no longer added to queue for future processing. Normally job will be marked as failed after it exceed given execution time, max attempts, max exceptions, etc. Instead of using above methods you can manually fail a job using fail() method.

    1. Fail() method does not output any messages to logs or terminal window.
    2. Any message passed with fail() method will stored in the failed_jobs table.

    Example

     ....
    
    class ProcessData implements ShouldQueue
    {
      
        ....
    
        /**
         * Execute the job.
         */
        public function handle(): void
        {
            Log::info('Processing... Data Job');
            if(true){
                $this->fail("Something went wrong");
                return;
            }
        }
    }

    In the queue worker terminal you will see job is marked as FAIL

    Job fail status on Terminal

    Why manually failed jobs show both fail and done in the queue worker terminal.

    • Fail status is due to marking the job with fail() method.
    • Done status is to mark that job execution process is completed even though job is failed.