Skip to content

failed() メソッド ― 失敗に誰も気づかなかったら

📖この章のキーワード
用語意味なぜ重要か
failed()全リトライ失敗後に呼ばれるメソッドログ記録や状態更新の最後の機会
failed_jobs テーブル失敗した Job が記録されるテーブル後から原因調査と再実行ができる
例外の握りつぶしcatch して再 throw しないことリトライと failed_jobs が無効化される
可観測性失敗に気づける仕組みログ、状態更新、アラートの組み合わせ

Phase 1: 観察

failed() メソッドを実装している Job と、していない Job を比較してみましょう。

failed() あり:

php
// UpdateFriendProfilesBatch.php (excerpt)
// Label: exemplar

class UpdateFriendProfilesBatch implements ShouldQueue
{
    public int $tries = 3;

    public function failed(\Throwable $exception): void
    {
        Log::error('UpdateFriendProfilesBatch failed permanently', [
            'progress_id' => $this->progressId,
            'error' => $exception->getMessage(),
        ]);

        // 進捗レコードを「失敗」に更新
        $progress = FollowerFetchProgress::find($this->progressId);
        if ($progress) {
            $progress->markFailed($exception->getMessage());
        }
    }
}
php
// FetchLineFollowerIds.php (excerpt)
// Label: exemplar

public function failed(\Throwable $exception): void
{
    Log::error('FetchLineFollowerIds failed', [
        'bot_id' => $this->botId,
        'error' => $exception->getMessage(),
    ]);

    // 進捗レコードを「失敗」状態に
    FollowerFetchProgress::where('bot_id', $this->botId)
        ->where('status', 'processing')
        ->update(['status' => 'failed']);
}

failed() なし:

php
// SendMessage.php (excerpt)
// Label: trade-off

public function handle(): void
{
    try {
        // LINE 送信...
    } catch (\Exception $e) {
        // ステータスを更新するが、例外を再 throw しない
        $message->update(['status' => Message::STATUS_FAILED]);
        // → failed_jobs テーブルにも入らない
        // → Laravel のリトライ機構も発動しない
    }

    // failed() メソッドが定義されていない
}

Phase 2: 判断

AI禁止ゾーン
  • failed() メソッドがある Job とない Job で、3 回失敗した後 に何が違いますか?
  • SendMessage は例外を catch して握りつぶしています。これの 問題点 は何ですか?
  • failed() の中で ログだけ書く のと、関連レコードの状態も更新する のでは何が違いますか?

AIに聞く前に、自分の頭で考えてみましょう。

テキストを入力すると有効になります