Exceptions Cause Retries0:00
So far, we've only reviewed the happy path for a job. But what if an exception or an error is thrown? Take a look. Here's our job. I'm just going to immediately throw an exception. OK. Now watch what happens. We will boot up our worker. And then in Safari, we'll give this a refresh to throw the job onto the queue. So everything seems OK from the user's end.
And then in Safari, we'll give this a refresh to throw the job onto the queue. So everything seems OK from the user's end. But if we look behind the scenes, notice it keeps trying to job over and over and over. It's going to blow up your system if you're not careful. Not to mention, if I visit the logs for today, you'll see Sublime's taking a long time to load because it just kept throwing new exception logs into this file. OK. So you have to be careful about this. If you're running a job that has the potential to error out or throw an exception, which is very, very likely, you must always set the number of tries.
Configuring Tries and Timeout0:50
If you're running a job that has the potential to error out or throw an exception, which is very, very likely, you must always set the number of tries. And in fact, I think there should be a default. And I'm sure there's a good reason why the default is zero. But nonetheless, be careful because if you don't set the tries, you're going to be in trouble if there is an issue. So anyways, if I say php artisan queue:work and we review the help for that, these two are important to consider. The tries is how many times should I try this job before I give up and I throw it into a failed job.
The tries is how many times should I try this job before I give up and I throw it into a failed job. Timeout will be, well, if this is a long-running job, how long will I wait and try to get this job done before I give out? OK. So let's set a maximum number of tries to 3. OK. So now let's give it one more shot, refresh, but now you'll see it tried a total of 3 times to process that job before it gave up, basically. And this will be true for any job that throws an exception, as you see there.
Tracking Failed Jobs1:46
times to process that job before it gave up, basically. And this will be true for any job that throws an exception, as you see there. But now, where does this job go? Well, again, if we list the queue commands, you will see these two here, queue:failed. List all of the failed queue jobs. But if you run that, BaseTableNotFound, and notice failed jobs. So yeah, what you'll want to do is set up a table that exclusively tracks any of your failed jobs. And because this is common, again, Laravel will do it for you, and that's what this command is for.
Creating failed_jobs Table2:20
And because this is common, again, Laravel will do it for you, and that's what this command is for. All right. Let's run it. Create a migration for a failed_jobs table, and I'll go ahead and migrate it. OK. So if you want to take a look at that, let's give this a refresh, you now have this new table called FailedJobs that Laravel created. And if we take a look at the structure, the connection will be, in our case, Redis. We're on the default queue.
And if we take a look at the structure, the connection will be, in our case, Redis. We're on the default queue. We have the payload, the exception that was thrown, and when it was thrown. OK. So let's run queue:work again, and then throw a job onto the queue by refreshing. OK. And now it runs three times before giving up and throwing the job into the failed_jobs table. So now, if I switch back and review the data here, let's clean this up a little bit. OK. Now you can see we have a new record.
Reviewing and Retrying Jobs3:35
The next step is for you to review this. So we would look and say, OK, yeah, it looks like, for whatever reason, for this payload, an exception of whoops was thrown. Let's try to fix the bug. So we go to the job, we find, usually it's going to be a little more cryptic than this, but we find what the issue is, and we'll fix it. And now, we can retry that failed job. So let's look at our queue namespace again. OK. So we're going to retry a failed job.
OK. So we're going to retry a failed job. Now we can either retry all of the failed jobs or a specific one. So if you want to do a specific one, you need to give it the ID. In this case, it's 1. Alternatively, you could do all to retry everything. OK. So now what happens is, it removes this record from the failed jobs table. If I refresh, it's gone. And it throws it back onto the queue.
If I refresh, it's gone. And it throws it back onto the queue. But don't forget, we're not running a queue:work at the moment, so let's do it one more time. queue:work. Aha! Now, because we fixed the error, it retried the job, and it processed it successfully. And that's it for this episode. So some key things to be aware of. Whenever you're running your queue:worker, set a maximum number of tries, and you might
So some key things to be aware of. Whenever you're running your queue:work, set a maximum number of tries, and you might want to set a timeout limit as well. Then, on the condition that you do have a failed job, it will be thrown into your failed_jobs table, at which point you can review them, fix the error, and then retry them when you're ready.
