Queue control and chaining

Laravel queues are powerfull and often adds quite a lot of flexibility to the system. While this is great – it can be very tricky to manage their priorities and ensure that they only run in specific order or if it’s really important – you run it as a priority over everything else.

Laravel Horizon

The best tool to check what your queues are doing and have some insights on how long it takes or what processes you are running is Laravel Horizon: https://laravel.com/docs/5.7/horizon

Horizon dashboard view

The dashboard lets you see how many jobs you process per minute/hour, how many of them have failed and check max wait times until a job gets picked up. Next cool thing is a debugging perspective – you can re-run a failed job in case something odd happened.

All in all – horizon is a great tool that you should use in your daily projects that use queues (even if it’s just for emails)

Queue prioritizing

Laravel queues can have multiple levels of priorities with different workers created. In the example window above we have 3 queue workers: default, high and low. By default all jobs will go to a default worker and that is great untill you have 1000 jobs waiting each minute and need to run something ASAP. Here’s where queue differential may come in handy:

dispatch((new RunPaymentProcess)->onQueue('high'));

This call will send RunPaymentProcess on high queue line and will result in no.1 priority over other jobs. Of course, to do that – you’ll need to be running a prioritised queue worker with following command (or if using a horizon, then it will run by default):

php artisan queue:work --queue=high,default,low

This will ensure that all high priority tasks will be ran before any of the default or low priority tasks. This is very great to differentiate between queue job that needs more attention or no attention at all.

Queue chaining

In case of queues that should run one after another – you could chain up them with the following code example:

Which will run in the order that we’ve written there – PaymentJob -> InvoiceJob -> AddFeatureJob. If any of them will fail – none of the following will be running and the queue will stop. This is great if following jobs are depending on the data that is altered on the previous jobs.

Bonus:

dispatch_now(…) – will dispatch a job immediately, like it is an async process.dispatch(…)->delay(now()->addMinutes(30)) – will postpone the execution by 30 minutes