第09回: Queue再試行と失敗ジョブ設計 — 「失敗する前提」でジョブを設計していますか?

章: 第4章: 非同期処理とイベント駆動

外部APIへの接続が一時的に失敗したとき、ジョブがそのまま消えてしまう――これはジョブの 失敗設計がない 状態で起きる定番の事故です。「たまに失敗する」と「常に失敗する」の間にある状態を放置すると、運用後に大きな手戻りを召います。

LaravelのQueueには triesbackoff といった 失敗制御の仕組み が備わっています。ジョブ作成時にこれらを設定することで、一時障害を彼らで待つ自後のくなる地設計を実現できます。

なぜQueue失敗設計が重要なのか

triesbackoff を設定せずになりじみな再試行を任せると次の問題が起きます。

  • 外部APIが復旧する前に最大試行回数に達し、ジョブが失敗テーブルに落ちる
  • 短時間に大量の再試行が発生し、障害復旧中のサーバーを加速させる(サンダーヘルド)
  • failed() メソッドを定義せず、障害発生をチームが知れない

チェックポイント: backoff に数列を渡すと再試おきに待機時間を増やせます(Exponential Backoff)。外部APIへの再試時は必ず使いましょう。

tries/backoffの設定指針

設定項目 推奨値 理由
$tries 3~5回 無限ループを防ぐ最低限必要
$backoff [10, 30, 60, 120] 復旧待機の時間を容許する
$timeout 60~300秒 處理とチェックが走る冥
failed() ログ・通知 失敗時にチームへ通知

実装例


<?php
class SyncInventory implements ShouldQueue
{
    public int $tries = 5;
    public array $backoff = [10, 30, 60, 120];

    public function handle(InventoryClient $client): void
    {
        $client->sync();
    }

    public function failed(\Throwable $e): void
    {
        logger()->error('在庫同期に失敗', ['error' => $e->getMessage()]);
    }
}

まとめ & 次のステップ

  • triesbackoff はジョブ作成時に必ず設定する習慣をつける
  • failed() で失敗通知を実装することで、失敗ジョブを流すのを防ぐ
  • $maxExceptions で不再試行の例外タイプを指定できる
  • php artisan queue:failed で失敗ジョブ一覧を確認し、retry で再実行できる

次回は 第10回: HorizonでQueue監視 で、Queue処理の状態をダッシュボードで可視化する方法を学びます。

Related Articles