#21 Laravel基礎

キューとジョブで非同期処理を実装する

キューとジョブの処理フロー バックグラウンド処理 アプリ dispatch() キュー jobs_table ワーカー queue:work ジョブ実行 handle() Job::class ジョブ登録 即レスポンス redirect() 完了 job processed 待たずに返す ジョブを取り出して処理 リクエストフロー 即時返却(非同期) キュー取り出し
図1: キューを使った非同期処理の流れ

キューとは

キュー? 処理を非同期で実行する仕組み。メール送信や画像変換など時間のかかる処理をバックグラウンドで行い、レスポンスを速くできる。 は、処理をすぐ実行せずに「後でやること」のリストに追加して、バックグラウンドで実行する仕組みです。

メール送信・画像変換・外部APIへのリクエストなど、時間のかかる処理をキューに投げることでレスポンスを速くできます。


キューの設定

# 📁 .env

QUEUE_CONNECTION=database  # database / redis / sync(同期実行)

開発中は sync(すぐに実行)が便利です。本番では databaseredis を使います。

database ドライバーを使う場合はジョブを保存するテーブルが必要です。

# ジョブ用テーブルのマイグレーションを生成して実行
php artisan queue:table
php artisan migrate

ジョブを生成する

php artisan make:job SendWelcomeEmail

app/Jobs/SendWelcomeEmail.php が生成されます。

<?php
// 📁 app/Jobs/SendWelcomeEmail.php

namespace App\Jobs;

use App\Mail\WelcomeMail;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;

// ShouldQueue を implements するとキューで実行される
class SendWelcomeEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public User $user
    ) {}

    // キューで実行される処理
    public function handle(): void
    {
        Mail::to($this->user)->send(new WelcomeMail($this->user));
    }
}

ジョブをキューに投げる

// 📁 app/Http/Controllers/Auth/RegisteredUserController.php

use App\Jobs\SendWelcomeEmail;

public function store(Request $request)
{
    $user = User::create([...]);

    // dispatch() でキューに追加(すぐには実行されない)
    SendWelcomeEmail::dispatch($user);

    return redirect()->route('dashboard');
    // ← メール送信を待たずにすぐリダイレクト!
}

遅延実行(Delay)

// 10分後にジョブを実行する
SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(10));

キューワーカーを起動する

ジョブはキューに溜まるだけで、実行するには「ワーカー」プロセスを起動する必要があります。

# キューワーカーを起動(Ctrl+C で停止)
php artisan queue:work

# 1件だけ処理して停止
php artisan queue:work --once

# タイムアウトと最大試行回数を設定
php artisan queue:work --timeout=60 --tries=3

開発中は別のターミナルで queue:work を起動しておくと、ジョブがリアルタイムで処理されます。


ジョブの失敗を処理する

ジョブが最大試行回数を超えて失敗した場合の処理を書けます。

// 📁 app/Jobs/SendWelcomeEmail.php

// 試行回数の上限
public int $tries = 3;

// ジョブが全試行失敗したときに呼ばれる
public function failed(\Throwable $exception): void
{
    // Slack通知やログを残す
    \Log::error("ウェルカムメール送信失敗: {$this->user->id}", [
        'error' => $exception->getMessage(),
    ]);
}

失敗したジョブは failed_jobs テーブルに記録されます。

# 失敗したジョブを再試行
php artisan queue:retry all

# 失敗したジョブの一覧を確認
php artisan queue:failed

キューを使わずに即時実行したいとき

テストなどで同期実行したい場合:

// dispatchSync() は ShouldQueue でも即時実行する
SendWelcomeEmail::dispatchSync($user);

まとめ

  • ShouldQueue インターフェースを実装したクラスがキュージョブ
  • dispatch() でキューに追加し、ワーカーがバックグラウンドで処理する
  • php artisan queue:work でキューワーカーを起動する
  • delay() で遅延実行できる
  • 失敗したジョブは failed_jobs テーブルに記録され、queue:retry で再試行できる

次回は通知(Notification)機能を学びます。