در حال بارگذاری ...

Configuring Retries and Backoff0:00

Dispatching jobs to the queue isn't a fire and forget kind of thing. We need to monitor our jobs and handle failures. Also, while designing our jobs we need to keep in mind that the job may fail. For example, this job here sends an email. What if the email provider API went down temporarily? An exception will be thrown and the job will fail. It's a good idea to configure automatic retrying so Laravel retries our job for a number of times. For that reason, we are using the tries public property on the job class and we are configuring the job to retry for three times. And we have seen in a past episode that when a job attempt fails, Laravel is going to release the job back to the queue. And if the queue is empty, a worker may beg that release job immediately to run it. In some cases though, we may want to wait between tries. Like in our example here, we need to wait a bit to

is empty, a worker may beg that release job immediately to run it. In some cases though, we may want to wait between tries. Like in our example here, we need to wait a bit to give a chance to the mailing provider to come back from its temporary outage. For that reason, we can use a backoff. To configure a backoff similar to the tries property, we're going to add a public property called backoff. So here with backoff of value two, when this job fails, the worker is going to wait two seconds before retrying it again. We can also configure an exponential backoff. And we do that by providing an array instead of a static value. And in that case here, the worker is going to wait two seconds after the first attempt and three seconds after the second attempt and before the final and third attempt. We can configure any number of values for the backoff array. And if the number of tries

Inspecting and Retrying Failures1:37

attempt and three seconds after the second attempt and before the final and third attempt. We can configure any number of values for the backoff array. And if the number of tries is more than the number of values in the array, Laravel is going to use the last value for all future attempts. So here in our example, it's going to wait for two seconds after the first attempt, 10 seconds after the second attempt, and 20 seconds after the third attempt and any other attempt in the future. Now what if a job keeps failing even after retrying it automatically? In that case, Laravel is going to store the job in a database table for us to inspect and retry later. Let's try that. So let's remove the backoff now, we don't need it, and configure the job to try for one time before it fails. Now let's go to the terminal and start a worker, php artisan queue:work, and then dispatch the

don't need it, and configure the job to try for one time before it fails. Now let's go to the terminal and start a worker, php artisan queue:work, and then dispatch the job by visiting the route. And as we can see, the job was attempted for one time, and then it was marked as failure. Now if we go to SQLPro, we can see the failed attempt stored in the failed_jobs database table. And we can grab the job unique ID and use it to retry the job manually if we want. So let's go to the terminal and call php artisan queue:retry, and then pass the job unique ID. And as we can see, Laravel pushed the job back to the queue. If we start a worker again, it's going to find the job pushed back to the queue and it's going to attempt it again. Now retrying doesn't have to always be because of an exception that was thrown from inside the job code. In some cases, we may want to

Releasing Jobs with Delay3:16

the queue and it's going to attempt it again. Now retrying doesn't have to always be because of an exception that was thrown from inside the job code. In some cases, we may want to push a job back to the queue to be retried later. Imagine a job that makes an HTTP request to a service that has a rate limit. If a job hits that rate limit, we will want to release the job back to the queue to be retried later when the rate limiter allows more requests. To do that, we can call the release method inside the job class. So let's go back to php store. Now the release method accepts a delay. This will override the back off value that we provide for the job. So for example, we can say delay for 30 seconds. This means that this job is going to be released back to the queue and it will not be retried again before 30 seconds. For the sake of our example, let's just wait for two seconds. And before

that this job is going to be released back to the queue and it will not be retried again before 30 seconds. For the sake of our example, let's just wait for two seconds. And before we test that, let's configure the number of tries to be 3 times. Now let's go to the terminal and start a worker php artisan queue:work and dispatch the job by visiting the route. And we can see that worker picked a job and it released it back to the queue. The worker picked it up again after two seconds to be retried. And because we are releasing it back to the queue in the handle method, each time the worker is going to process the job it is going to release it back to the queue to be attempted for the allowed number of tries. And if you look closely, we configure the job to be retried for only 3 times. But from the output in the terminal, we can see that it was retried one, two, three,

number of tries. And if you look closely, we configure the job to be retried for only three times. But from the output in the terminal, we can see that it was retried one, two, three, and fourth time. And it was only marked as failed after the fourth attempt. And the reason for that is that the worker processed the job the first time and it was released, processed it for the second time, and it was released. And then it processed it for the third time, which is an allowed attempt because we have tries equal three, and then the job was released back. And when the worker picked it up again, after the third attempt, it found that it was only configured to retry for three times. So it didn't even run it, it considered it as a failure immediately. I hope that makes sense. Now you should also know that to Laravel retrying the job due to an exception is the same as

Limiting Retries by Exceptions5:47

as a failure immediately. I hope that makes sense. Now you should also know that to Laravel, retrying the job due to an exception is the same as retrying it because we manually released it back to the queue. Each attempt is counted and if we have tries set to three, the job can only be attempted three times, whether it's because of an exception or thrown, or because we released it back manually to the queue. Sometimes it makes more sense to allow a job to be retried as many times as it needs when we release it back to the queue, but only retried a couple of times or a few times if an exception was thrown. For that reason, we can configure the maximumExceptions public property. So it's similar to having the tries property, but instead we are going to use maximumExceptions.

we can configure the maximum exceptions public property. So it's similar to having the tries property, but instead we are going to use maximum exceptions or maxExceptions. And we configure it to try for two times. Now we can configure the tries or the attempts to be 10 in total, but two of them can be because of an exception that was thrown. So to test this real quick, let's move the sleep method and we configure the job to be released to the queue and be retried immediately. Now let's go to the terminal, clear it and start a worker php artisan queue:work. Let's dispatch the job by visiting the route. And we can see here that the job was retried for 10 times, because we are releasing it back to the queue and we configure tries to be for 10. Now to show you the difference, let's throw

Handling Job Failure Callback7:16

for 10 times, because we are releasing it back to the queue and we configure tries to be 10. Now to show you the difference, let's throw an exception instead. And then go back to the terminal and clear it php artisan queue:work, and then dispatch the job by visiting the route. And as you can see, it was only retried for a couple of times because we configured the allowed exceptions or the maximum exceptions to be only 2. So far so good. But there's another convenient feature of the Laravel queue system that I want to share with you. And it's the ability to configure some code to run when a job fails. We can do that by implementing a failed method inside the job class. So we go here and create a public method, it's called failed.

We can do that by implementing a failed method inside the Job class. So we go here and create a public method, it's called failed. This method accepts an instance of the Exception that was thrown and caused the job to fail. Inside this method, we can write any code that Laravel is going to run when the job fails. For the sake of our example, we are just going to print an output to the log. Now let's go to the terminal and start a worker php artisan queue:work. Dispatch the job by visiting the route. And the job was attempted for two times before it's considered a failure. And if we go back to PhpStorm and visit the log file, we can see the exception that was thrown from inside the job. And we can also see the message that we printed inside the failed job of the Job class here.

log file, we can see the exception that was thrown from inside the job. And we can also see the message that we printed inside the failed job of the Job class here.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟