Exceptions can be thrown during job handling. This can be internal errors which result of poorly written code, and external, when the requested services and external resources are unavailable. In the second case, it's good to be able to retry a job after time.
There are several ways to do this.
The first method is implemented by the component options:
'components' => [
'queue' => [
'class' => \yii\queue\<driver>\Queue::class,
'ttr' => 5 * 60, // Max time for anything job handling
'attempts' => 3, // Max number of attempts
],
],
The ttr
option sets time to reserve of a job in queue. If a job doesn't executed during this time,
it will return to a queue for retry. The attempts
option sets max number of attempts. If attempts
are over, and the job isn't done, it will be removed from a queue as completed.
The options extend to all jobs in a queue, and if you need to change this behavior fo several jobs, there is second method.
Separate control of retry is implemented by RetryableJobInterface
interface. For example:
class SomeJob extends BaseObject implements RetryableJobInterface
{
public function execute($queue)
{
//...
}
public function getTtr()
{
return 15 * 60;
}
public function canRetry($attempt, $error)
{
return ($attempt < 5) && ($error instanceof TemporaryException);
}
}
getTtr()
and canRetry()
methods have a higher priority than the component options.
The third method to set TTR and the need to retry of failed job involves using
Queue::EVENT_BEFORE_PUSH
and Queue::EVENT_AFTER_ERROR
events.
Queue::EVENT_BEFORE_PUSH
event can be used to set TTR:
Yii::$app->queue->on(Queue::EVENT_BEFORE_PUSH, function (PushEvent $event) {
if ($event->job instanceof SomeJob) {
$event->ttr = 300;
}
});
And Queue::EVENT_AFTER_ERROR
event can be used to set a new attempt:
Yii::$app->queue->on(Queue::EVENT_AFTER_ERROR, function (ErrorEvent $event) {
if ($event->job instanceof SomeJob) {
$event->retry = ($event->attempt < 5) && ($event->error instanceof TemporaryException);
}
});
Event handlers are executed after RetryableJobInterface
methods, and therefore have the highest
priority.
Full support of retryable implements for Beanstalk, DB, File, AMQP Interop and Redis drivers. Sync driver will not retry failed jobs. Gearman driver doesn't support of retryable. RabbitMQ has only its basic retryable support, in which an attempt number can not be got.