Working with Laravel Queues

Laravel queues help to defer the processing of heavy/time-consuming tasks. The benefits of the queue are to not interrupt website visitor with slow performances. Laravel provides a variety of queue backends like Beanstalk, Amazon SQS, Redis, Database and synchronous driver.

Table of content

Configure Queue Connection

Laravel has various built-in drivers to establish the connection for a queue, so you don’t need the extra plugins. These drivers are the database, Beanstalkd, Amazon SQS, Redis, and synchronous. You can define the driver for queue connection with QUEUE_CONNECTION in your .env file. You can check the provided drivers setting at the config/queue.php file.

....

'connections' => [

    'sync' => [
        'driver' => 'sync',
    ],

    'database' => [
        'driver' => 'database',
        'table' => 'jobs',
        'queue' => 'default',
        'retry_after' => 90,
    ],

    'beanstalkd' => [
        'driver' => 'beanstalkd',
        'host' => 'localhost',
        'queue' => 'default',
        'retry_after' => 90,
    ],

    'sqs' => [
        'driver' => 'sqs',
        'key' => env('SQS_KEY', 'your-public-key'),
        'secret' => env('SQS_SECRET', 'your-secret-key'),
        'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
        'queue' => env('SQS_QUEUE', 'your-queue-name'),
        'region' => env('SQS_REGION', 'us-east-1'),
    ],

    'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
        'queue' => env('REDIS_QUEUE', 'default'),
        'retry_after' => 90,
        'block_for' => null,
    ],

],

....

In our case, we are using the database driver. To use the database driver, we need the database to hold the jobs. To do so, run the command to generate the jobs table.

php artisan queue:table
php artisan migrate

Create the First Job

Laravel has the artisan make:job command to create a job. All these created jobs will be stored in the app/Jobs directory.

php artisan make:job SendEmail

The file could be similar to the below codes.

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class SendEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

Now we are sending emails through this job to any user. Follow the link to know more about Laravel Mail.

namespace App\Jobs;

use Mail;
use App\Mail\WelcomeMail;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class SendEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    

    public $email;


    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($email)
    {
        $this->email = $email;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        Mail::to($this->email)->send(new WelcomeMail());
    }
}

Dispatch Job

Laravel provides a global function to dispatch any job i.e. dispatch() function. Let’s say we have some controller and it has a method that requires the user id to access that method. And we will dispatch our job through that method.

....

public function welcome($userId)
{
    $user = \App\User::find($userId);
    dispatch(new \App\Jobs\SendEmail($user->email));

    return redirect()->route('some.other.route');
}

....

Laravel has more flexibility to handle queues during dispatch time. You can add delay dispatching, connection, queue etc.

dispatch(
    new \App\Jobs\SendEmail($user->email)
        ->delay(now()->addMinutes(10))
        ->onConnection('database')
        ->onQueue('welcome_queue');
);

So if you are applying queue to production environment then you need supervisord installed on your production server. Or run the following command through the terminal to dispatch these queues.

php artisan queue:work database --queue=welcome_queue,default

In the above command, we have defined the connection which is database and the custom queue (welcome_queue) and the default queue.

Resources