In your web development career, at some point, you will need to build a feature that does any of these things:
- hit an API server that can potentially take a long time to load or return a response,
- execute a longer running script; for instance a backup archive, resizing images or sending emails to many users
As these tasks are usually initiated by an authenticated user, one would often wait for that request to be send from a click of a button (POST action or API request) and then dispatched. Meanwhile the user has to wait for the requested action to complete before the page continues loading.
In modern web technology web servers and underlying proxies protect visitors to your website by allowing a timeout to be configured. Long running tasks, like the above, potentially are partially completed or choke up when the user sees an error and retries the action multiple times.
In this scenario it's always wise to look at a different mechanism to process the task. Offloading these tasks to alternate processes (outside of the user request) is where performant, user friendly applications are guaranteed. Queues are the industry standard nowadays and Flarum has built-in support for them, so dispatching jobs to the queue will cause Flarum to process them. By default Flarum uses the Laravel sync
driver, which means that the task is still processed in the same request that the user requested the task to be executed.
When writing extensions you have to be aware about timeouts, about long running tasks executed at whim based on user interaction or other triggers. Those naturally should flow into a queue.
Here are some articles to further familiarize you with queues:
Flarum example
Now dispatching in Flarum (which does not use Facades) is slightly different than the way Laravel does this. Instead of calling on the Facade or using the job itself Job::dispatch()
we resolve the Queue interface:
use Illuminate\Contracts\Queue\Queue;
/** var Queue $queue **/
$queue = resolve(Queue::class);
$queue->push(new YourLongRunningJob);
When defining your job, make sure to re-use the Flarum abstract, like so:
use Flarum\Queue\AbstractJob;
class YourLongRunningJob extends AbstractJob
{}
This reduces the need to apply the contracts that the queue needs for processing.