Skip to content

Queues/Workers

Some tasks, like processing large CSV uploads, can slow down your app and hurt the user experience. Leaf makes it easy to offload heavy work to background jobs, keeping your app fast and responsive. With built-in queuing, you get better performance without the complexity.

Queues are only supported by Leaf MVC. We plan to add support for Leaf Core in the near future.

Leaf queues have three parts: the queue (stores jobs), the job (task to run), and the worker (processes jobs). You push jobs to the queue, and the worker processes them.

Installation

To get started with Queues in Leaf, you need to install the leaf/queue package:

bash
leaf install queue@v4.0-beta
bash
composer require leafs/queue:v4.0-beta

This will install the Leaf Queue package and set up the necessary files and commands for you to start using queues in your Leaf app.

By default, Leaf MVC uses your database as the queue backend, storing jobs in a leaf_php_jobs table. If you're fine with these defaults, just restart your server—Leaf will detect the queue setup and automatically start processing jobs alongside the PHP and Vite servers.

Creating a job

Jobs handle background tasks like sending emails after user registration. Instead of delaying the response, you can dispatch a job to the queue, keeping your app fast and responsive.

You can create a new job using the g:job command:

bash
php leaf g:job SendEmail

This creates a SendEmailJob class in app/jobs with a handle() method that runs when the job is processed. You can add any logic here, like using UserMailer to send an email:

php
<?php

namespace App\Jobs;

use Leaf\Job;
use App\Mailers\UserMailer;

class SendEmailJob extends Job
{
    /**
     * Handle the job.
     * @return void
     */
    public function handle($userId)
    {
       UserMailer::welcome($userId)->send();
    }
}

Dispatching a job

After creating a job, you can dispatch it to the queue using the global dispatch() function:

php
dispatch(SendEmailJob::class);

Some jobs like the send email job above may require some data to be passed to the job. You can pass data to the job using the with() method on the job:

php
dispatch(SendEmailJob::with($userId));

You can also dispatch multiple jobs at once:

php
dispatch([
  SendEmailJob::with($userId),
  SendReminderJob::with($userId),
  ScheduleFlightJob::with($userId),
]);

Specifying options for a job

There are times when you need a job to behave a specific way, for instance, you may want to delay a job for a few minutes or specify the number of times a job should be attempted. You can do that by directly setting the options on the job:

php
<?php

namespace App\Jobs;

use Leaf\Job;
use App\Mailers\UserMailer;

class SendEmailJob extends Job
{
    protected $delay = 10; // add 10 sec delay //
    protected $tries = 1; // try job only once (default 3) //

    /**
     * Handle the job.
     * @return void
     */
    public function handle($userId)
    {
       UserMailer::welcome($userId)->send();
    }
}

The available options are:

OptionDescription
delayThe number of seconds to wait before processing a job.
delayBeforeRetryThe number of seconds to wait before retrying a job that has failed.
expireThe number of seconds to wait before archiving a job that has not yet been processed.
forceWhether to force the worker to process the job, even if it has expired or has reached its maximum number of retries.
memoryThe maximum amount of memory the worker may consume.
timeoutThe number of seconds a child process can run before being killed.
triesThe maximum number of times a job may be attempted.

Without a worker running, your jobs will just sit in the queue without being processed.

Limitations of Queues/Workers

Just as with every other aspect of Leaf, we try to set everything up for you so you can get started right after running leaf install. This makes Leaf's queue system very easy to use, but it also comes with some limitations:

  • Queues are completely stateless. This means that you can't access the current request, user, session, or any other stateful data in your jobs. If you need to access the current request, you should pass the necessary data to the job as a parameter.
  • Due to its simplicity, Leaf's queue system is not as feature-rich as other queue systems like Laravel's. We are working on adding more features to the queue system.

Configuration

If you want to change the default config for the queues and workers, you need to publish the queue config file using the MVC console:

bash
php leaf config:publish queue

This will generate a queue.php file in your config directory which looks something like this:

php
<?php

return [
    /*
    |--------------------------------------------------------------------------
    | Default Queue Connection
    |--------------------------------------------------------------------------
    |
    | Here you may specify which of the queue connections below you wish
    | to use as your default connection for all queue work.
    |
    */
    'default' => _env('QUEUE_CONNECTION', 'database'),

    /*
    |--------------------------------------------------------------------------
    | Queue Connections
    |--------------------------------------------------------------------------
    |
    | Here you may configure the connection options for every queue backend
    | used by your application. An example configuration is provided for
    | each backend supported by Leaf. You're also free to add more.
    |
    | Drivers: "database", "redis (BETA)", "file (WIP)"
    |
    */
    'connections' => [
        'database' => [
            'driver' => 'database',
            'connection' => _env('DB_QUEUE_CONNECTION', 'default'),
            'table' => _env('DB_QUEUE_TABLE', 'leaf_php_jobs'),
        ],

        'redis' => [
            'driver' => 'redis',
            'connection' => _env('REDIS_QUEUE_CONNECTION', 'default'),
            'queue' => _env('REDIS_QUEUE', 'default'),
        ],
    ],
];

You can set up multiple queue connections, and Leaf will connect to them when a job is run. For now, only database queues are supported, but we are working on redis and file drivers which will be available pretty soon.

Using a different connection

Once you have configured another database connection, you can run a job using that queue connection by specifying it inside the job you create like this:

php
<?php

namespace App\Jobs;

use Leaf\Job;
use App\Mailers\UserMailer;

class SendEmailJob extends Job
{
    protected $connection = 'myOtherConnection';

    /**
     * Handle the job.
     * @return void
     */
    public function handle($userId)
    {
       UserMailer::welcome($userId)->send();
    }
}

From there, you can dispatch the job just as you always do:

php
dispatch(SendEmailJob::with($userId));

Deployment

Leaf sets up the necessary files and commands for you to start using queues in your Leaf app. However, once deployed, you’ll need to set up your server to keep your workers running continuously. Check out this guide on deploying queues/workers for more information.

Released under the MIT License.