How to delete jobs from a redis queue in Laravel
If you type "how to delete a job from a Redis queue in Laravel" into your favourite search engine, you'll get quite a few stackoverflow and blog posts giving you different ways of doing it. However not all of them are quite what you want. A lot involve just clearing out the database, by clearing the queue or going into Redis and flushing everything.
This might be fine if you're working locally, but in a production enviroment, this just won't do.
I've also fallen foul of this. To the point where I needed to build a simple reminder feature where you could set a reminder to happen in the future which sends an email. I didn't think it through properly and when it came to deleting the reminder, I quickly came to the conclusion - there's no easy way to delete a single job from a redis queue.
There is however a (slightly) less messy way to delete a job from a database queue and this is the approach I took. Looking back on it, it wasn't my best decision, but it worked. Anyway enough waffle, let's get to the answer.
How to delete a job from a redis queue
Short answer - don't bother. You don't need to! You only need to change the way you think about it. If you feel like closing the tab right now, don't - just keep reading, it's surprisingly easy!
So lets make up a fake scenario, you've got a reminder system which sends an email to a user at some point in the future, but you need to change or cancel it to stop the email going out.
Step 1
Add a status column to your database table, which accepts an 'active
' and 'deleted
' value. When a new reminder is created, set the status to active, queue up your job or notification as normal.
Step 2
When you need to change or cancel the reminder, simply update the status column to be 'deleted
'. You could then in your controller logic exclude all rows that are deleted so your user doesn't see them anymore.
Step 3
In your job or notification within the handle()
method. Simply add a check to see if the reminder has been cancelled or not and if it has, just return false. At this point your job will complete and do nothing. Much easier than trying to hunt down the job by its ID and deleting it! Problem solved with a simple early return! Here's an example to show you how:
public function handle()
{
// First check is reminder has been cancelled
if ($this->reminder->status == 'deleted') {
return false;
}
// Continue with email notification...
$this->reminder->user->notify();
This lightbulb moment came to me after reading the fantastic Laravel Queues in Action by Mohamed Said - A former Laravel core team member. There is a section in the first edition titled “Cancelling Abandoned Orders” which has the above check. So simple, yet so effective.
If you haven’t already purchased it, I’d highly recommend purchasing it. You will seriously level up your queue knowledge.