Laravel: Fail, Retry, or Delay a Queued Job From Itself

You probably didn’t know you can use these tricks

Image for post
Image for post
Photo by Emile Guillemot on Unsplash

When creating jobs, listeners, or subscribers to push into the queue, you may start thinking that, once dispatched, you’re all on your own with what the queue worker decides to do with your logic.

Well… it’s not that you can’t interact with the queue worker from inside the job, but you usually don’t need to… until you do.

The magic happens because of the InteractsWithQueue trait. When the queued job is being pulled out from the queue, the CallQueuedListener will check if it’s using the InteractsWithQueue trait, and if it is, the framework will inject the underlying “job” instance inside.

This “job” instance is like the driver that wraps your real Job class, which contains information about the connection and attempts, among other things.


I will use a transcoding Job as an example. This is a job that transcodes a podcast audio file into an MP3 of 192kbps. Because this is set in the free transcoding queue, it has limited availability.

Checking the Attempts

The first method is called attempts(), and as its name implies, it returns the number of attempts. A Job always starts with one attempt.

This method is meant to be used with others, like fail() or release() (delay). For illustration purposes, we will notify the user of the nth retrying: each time we try to transcode a podcast in the free queue, we will notify the user we’re retrying for the nth time, giving him the option to cancel future transcodes.

Telling the user that we’re retrying something for the nth time is useful when the logic has failed beforehand, letting the user (or developer) check what went wrong, but of course you can do more than that.

Personally, I like to do that after the Job failed, and if it has retries left, tell him that we’re going to retry later. Of course, this example is just for illustration purposes.

Deleting the Job

The second method is delete(). As you can guess, you can delete the current Job from the queue.

This can be handy when you shouldn’t process the job or listener after it was queued for several reasons. For example, think about this scenario: the publisher that uploaded the podcast has been deactivated for any reason (like a TOS violation) before the transcoding occurs, and we should not process the podcast.

We will add that code to the example from before:

If you need to delete the job on models that may have been deleted, you may want to set $deleteWhenMissingModels to true to avoid processing something that is not there.

Failing the Job

This is very, very handy when you need control over artificially failing the logic, because using an empty return statement will mark the Job as done successfully. You can forcefully fail the queued job, hopefully with an exception, allowing the handler to retry it later if possible.

This gives you finer control when the job fails. In any case, you can also use the failed() method, which allows you to perform any cleaning after it fails, like notifying the user or deleting something.

In this example, we will fail the job if the podcast cannot be retrieved from storage for whatever reason, like when the CDN goes down, throwing a custom exception.

Now, onto the final method.

Releasing (Delaying) a Job

This is probably the most useful method of the trait, as it allows you to push the job further into the future. This method is used for rate limiting your job.

Apart from rate limiting, you can also use this when something is not available but you expect it to be in the near future. Also, to avoid failing preemptively.

In this last example, we will delay the transcoding for later: if the transcoder is under heavy usage, we will delay the transcoding for five minutes until the load lowers.

We could use some magic, for example, getting assign some slots to the transcoder, and delay the job if the transcoder slots are full.

And that’s pretty much all you can do from inside the queued job. Happy queueing.

Better Programming

Advice for programmers.

Sign up for The Best of Better Programming

By Better Programming

A weekly newsletter sent every Friday with the best articles we published that week. Code tutorials, advice, career opportunities, and more! Take a look

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Italo Baeza Cabrera

Written by

Graphic Designer graduate. Full Stack Web Developer. Retired Tech & Gaming Editor.

Better Programming

Advice for programmers.

Italo Baeza Cabrera

Written by

Graphic Designer graduate. Full Stack Web Developer. Retired Tech & Gaming Editor.

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store