Skip to main content
Version: 1.x

Queues

Mantle provides a Queue interface for queueing asynchronous jobs that should be run in the background instead of blocking the user's request. The process is abstracted so that another queue provider could be used but only WordPress-backed queues are supported out of the box.

Mantle's Queue System Can Be Used In Any WordPress Project

Mantle's queue system is designed to be used in any WordPress project, not just those built with Mantle. You can instantiate the bootloader and then use the queue without any additional setup.

// Instantiate the bootloader.
bootloader()->boot();

// Dispatch a job.
dispatch( function () {
// Perform some task...
} );

Creating Jobs

Application jobs are stored in the apps/jobs directory. Jobs can be generated through the wp-cli command:

bin/mantle make:job Send_Welcome_Email

That will generate a new job class in app/jobs/class-send-welcome-email.php that looks like this:

namespace App\Jobs;

use Mantle\Contracts\Queue\Can_Queue;
use Mantle\Contracts\Queue\Job;
use Mantle\Queue\Dispatchable;
use Mantle\Queue\Queueable;

/**
* Send_Welcome_Email Job.
*/
class Send_Welcome_Email implements Job, Can_Queue {
use Queueable, Dispatchable;

/**
* Handle the job.
*/
public function handle() {
// Handle it here!
}
}

Dispatching Jobs

Once you have a job class you can dispatch to it from anywhere in your application.

use App\Jobs\Send_Welcome_Email;

Send_Welcome_Email::dispatch( $arguments_to_pass_to_constructor );

Any arguments passed to the dispatch method will be passed to the job's constructor. The job will be serialized and stored in the database until it is processed.

You can also dispatch using the dispatch helper function:

dispatch( new Send_Welcome_Email( $arguments_to_pass_to_constructor ) );

If you need any application services in your job, you can type-hint them in the handle method and they will be injected automatically:

namespace App\Jobs;

use App\Models\Post;
use App\Services\Example_Service;
use Mantle\Contracts\Queue\Can_Queue;
use Mantle\Contracts\Queue\Job;
use Mantle\Queue\Dispatchable;
use Mantle\Queue\Queueable;

class Send_Welcome_Email implements Job, Can_Queue {
use Queueable, Dispatchable;

/**
* Create a new job instance.
*
* @param Post $post
*/
public function __construct( public Post $post ) {}

/**
* Handle the job.
*/
public function handle( Example_Service $service ) {
// Service is automatically injected at runtime.
}
}

The above job can be dispatched like this:

$post = App\Models\Post::find( 1 );

Example_Job::dispatch( $post );

Dispatching Closures/Anonymous Functions

Closures can be dispatched to the queue as well. The closure will be serialized and unserialized when it is run. Dispatching an anonymous function is an incredibly powerful tool that can quickly take an expensive operation and move it to the background.

$post = App\Models\Post::find( 1 );

dispatch( function() use ( $post ) {
$post->perform_expensive_operation();
} );

Using the catch method, you may provide a closure that should be executed if the queued closure fails to complete successfully after exhausting all of your queue's configured retry attempts.

dispatch( function() {
// Perform some task...
} )->catch( function( Exception $e ) {
// Send the exception to Sentry, etc...
} );

Dispatch Synchronously

A job can be invoked synchronously and will be run in the current request.

Example_Job::dispatch_now();

Dispatching After the Request is Sent

If you need to dispatch a job after the response has been sent to the user, you can use the dispatch_after_response method. This is useful for deferring actions that should be executed after the response has been sent to the user but before the request is completed.

dispatch( function () {
// Perform some task...
} )->after_response();

// Or with a job class:
Example_Job::dispatch_after_response();

Multiple Queues

To allow for some priority between jobs a job can be sent to a specific queue. By default all jobs will be sent to the default queue. A job can be selectively sent to a smaller/different queue to allow for some priority among jobs.

// Sent to the 'default' queue.
Example_Job::dispatch();

// Sent to the 'priority' queue.
Example_Job::dispatch()->on_queue( 'priority' );

Dispatching to an isolated/smaller queue can be useful for ensuring that a specific job is processed before others. For example, a job that sends a welcome email to a new user might be sent to a welcome-email queue to ensure that it is processed before other jobs that are sent to a larger default queue.

Queue Worker

The queue worker is a scheduled task that runs via cron to process batches of queued jobs. When a queue job is dispatched, it is stored in the database and a queue worker batch is scheduled to run. The queue worker will process a batch of 5 jobs by default and can be configured via the queue.batch_size configuration value or QUEUE_BATCH_SIZE environment variable.

The queue worker also supports concurrent processing of job batches. By default, only a single batch will be processed at a time. For sites with a lot of queued jobs, it may be beneficial to process multiple batches concurrently. This can be configured via the queue.max_concurrent_batches configuration value or QUEUE_MAX_CONCURRENT_BATCHES environment variable. The default value is 1, meaning only a single batch will be processed at a time. A value of 2 would allow for two batches to be processed concurrently, and so on. The value should be adjusted based on the site's server resources and the number of queued jobs.

Jobs will be deleted from the queue after a week once they have either completed or failed. This can be configured via the queue.delete_after configuration value or QUEUE_DELETE_AFTER environment variable.

Queue Admin

The WordPress-powered queue includes an admin page for monitoring the queue status, reviewing pending/failed/completed jobs, and retrying failed jobs. It is accessible via the WordPress admin under the Tools menu:

Queue Admin