failed
メソッドの実行に失敗するLaravelのジョブクラスには、failed
というメソッドを実装することで、失敗時の処理を定義できます。
<?php
namespace App\Jobs;
// ...
class FooJob implements ShouldQueue
{
// ...
/**
* The job failed to process.
*
* @param Exception $exception
* @return void
*/
public function failed(Exception $exception)
{
// 失敗時に実行される
}
}
最近、このfailed
メソッドの実行自体がエラーになることがありました。
Argument #1 ($exception) must be of type Exception, TypeError given, ...
確認すると、原因は単なる引数の型の間違えでした。上記のようにException
を受け取っていたのですが、実際に渡されたのはTypeError
でした。
ご存知のように、PHPの例外は以下のようなツリー構造になっています。
- Throwable
- Error
- TypeError
...
- Exception
...
TypeError
はError
のサブクラスであり、Exception
のサブクラスではないので、failed
の実行が失敗するのは当然です。
しかしさて、なぜfailed
の第1引数をException
として実装してしまったのでしょうか。原因を探ってみました。
failed
は、artisan make:job
で用意されるものではなさそうでした。failed
を持って来た、という可能性はありません。failed
はException
を受け取る仕様であり、途中でそれが変わった可能性を考え、コミットログやアップグレードガイドをざっと見ましたが、その限りでは元々Throwable
を受け取る仕様だったようです。failed
の実装例はありました。が、型は正しくThrowable
でした。とりあえずここまで来て思い付くことがあり、古いバージョンのドキュメントを確認すると、そこには第1引数がException
になっている実装例がありました。これをコピペしたのが原因と考えてよさそうです。
<?php
namespace App\Jobs;
use Exception;
use App\Podcast;
use App\AudioProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessPodcast implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
protected $podcast;
/**
* Create a new job instance.
*
* @param Podcast $podcast
* @return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* Execute the job.
*
* @param AudioProcessor $processor
* @return void
*/
public function handle(AudioProcessor $processor)
{
// Process uploaded podcast...
}
/**
* The job failed to process.
*
* @param Exception $exception
* @return void
*/
public function failed(Exception $exception)
{
// Send user notification of failure, etc...
}
}
Queues - Laravel 5.3 - The PHP Framework For Web Artisans
公式ドキュメントのfailed
の実装例は何度か修正されており、5.3で引数を受け取るようになってから6までの間は、間違ったException
を受け取っていました。これは、以下のPRで修正され、7以降のドキュメントではThrowable
になっています。
さらに10で、引数がnullableに修正されています。
[10.x] Nullable failed
method by timacdonald · Pull Request #9445 · laravel/docs
ドキュメントの変更履歴がこうして残っているのは、やはり便利です。変更履歴や、そもそも古いバージョンのドキュメントが残っていなければ、原因究明は難しかったでしょう。
一方、コードであれば重要な修正はそれ自体がドキュメントにされやすいですが、ドキュメントの重要な修正がドキュメントにされるようなことはあまりなさそうで、ここは改善の余地がありそうです。
古くからあるジョブクラスのfailed
メソッドの引数の型は、一度確認してみてもいいかもしれません。
この文書はCC BY(クリエイティブ・コモンズ表示4.0国際ライセンス)で公開します。