LoginSignup
13
12

More than 3 years have passed since last update.

【Laravel】MaxAttemptsExceededExceptionと戦って気付いたこと

Last updated at Posted at 2020-12-25

MaxAttemptsExceededExceptionと10時間くらい戦って気付いたことを書きます。

環境

  • PHP 7.4.3
  • Laravel Framework 6.14.0

この例外 is 何

has been attempted too many times or run too long. The job may have previously timed out.

ジョブのタイムアウト時、もしくはジョブの試行回数が設定値を超えた場合に発生する。

この例外が発生する条件

この例外に関連する登場人物(設定値)は以下の3つ。

  • timeout
  • retry_after
  • tries

このいずれかの設定値が間違っていると、意図せずこの例外が吐かれる可能性がある。

設定値について

ジョブ自体に設定することもできるし、ジョブ実行時にオプションで設定することもできる。
どちらも設定した場合は、ジョブ自体に設定したほうが優先される。
retry_afterに関してはconfig/queue.phpでしか設定できないっぽい。

ジョブ自体に設定する場合

...

class ExampleJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Notifiable;

    public $timeout = 1; // タイムアウト秒数
    public $tries = 1; // 試行回数

    ...
}

ジョブ実行時に設定する場合

$ php artisan queue:work --timeout=1 --tries=1

retry_afterの設定

バックエンドサービスにdatabaseを使う場合の例です。

config/queue.php
    'connections' => [
        ...
        'database' => [
            'driver' => 'database',
            'table' => 'jobs',
            'queue' => 'default',
            'retry_after' => 1,
        ],
        ...
    ],

気付いたこと

timeoutを設定する場合、retry_afterも設定する必要がある

キュー 6.x Laravel
https://readouble.com/laravel/6.x/ja/queues.html

--timeout値は、最低でも数秒retry_after設定値よりも短くしてください。これにより、与えられたジョブを処理するワーカが、ジョブのリトライ前に確実にkillされます。--timeoutオプションをretry_after設定値よりも長くすると、ジョブが2度実行されるでしょう。

timeoutだけを設定して安心してはいけません。それは罠です。
retry_afterをtimeoutより長く設定しないと、ジョブが意図せず再試行され、MaxAttemptsExceededExceptionに繋がる可能性があります。

tries=0にするとfailedメソッドが動かなくなる

tries=0でジョブを実行すると、例外発生時にfailedメソッドが動作しません。
triesの設定値は1以上を推奨します。

余談

キューを使う上で知っておきたいこと も書いてみました。
こちらも参考になるかもしれません。

13
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12