【Laravel】 イベントのリスナーにキューを使用する方法

イベントを実行する際、時間のかかるイベントを実行したい場合があります。しかし、普通に同期で処理していてはその後の処理に響いてしまいます。そこで、イベントにキューを使用して裏で実行できるようにしてみましょう。

キューを使ったイベント

通常のイベントは同期で処理されます。しかし、例えばHTTP通信をするなど、長時間かかる可能性がある処理はキューを用いて非同期で実行させることができます。

キューイングシステムの設定はconfig/queue.phpにあります。

基本的な構造は同じで、リスナー側にShouldQueueを実装します。

class MyListener implements ShouldQueue
{
    // ...
}

あとは普通のイベントと同様に投げるだけです。これで非同期でイベントを処理できるようになり、重い処理を裏で、あるいは後で行うといったことが可能になります。

デフォルトでは同期で動作するため、裏で動かすようにしたい場合は設定を変更する必要があります。

キューでのイベントを試したいだけの場合、.envQUEUE_CONNECTIONの値をdatabaseに書き換え、php artisan queue:tablephp artisan migrateでテーブルを用意し、php artisan optimizeしてキャッシュをクリアして実行するのが楽です。

イベントを投げたら、そのキューが実行されるようにphp artisan queue:workする必要があります。

忘れがちですが、キューで動かすリスナーを更新した際はqueue:workし直す必要があります。

失敗したジョブの処理

キューを使用してリスナーを動かしたときに失敗した (一定回数再試行してダメだった) 場合、どのような処理を行うかをfailedメソッドに定義することができます。

class MyListener implements ShouldQueue
{
    public function handle(MyEvent $event)
    {
        Log::debug('MyListener handler');

        // 失敗した = 例外を排出した
        throw new Exception('sample error');
    }

    public function failed(MyEvent $event, $exception)
    {
        Log::error('Job Error: ' . $event->hoge());

        // 失敗したジョブの後始末
    }
}

キューに入れる条件を設定

キューに入れて実行するかどうかを状態によって決めたいという場合、shouldQueueメソッドをオーバーライドします。

trueを返せばキューに入り、falseを返せばキューに入らず実行されません。

class MyListener implements ShouldQueue
{
    /**
     * キューへ投入するかを決定
     * trueならキューに入れる
     */
    public function shouldQueue(MyEvent $event)
    {
        return $event->getValue() >= 50;
    }
}

キュー周りの設定

キューに入るリスナーでは、リトライ回数や使用するキューの設定等が可能です。

最大試行回数を設定するには$triesに回数を代入、タイムアウトを設定したい場合、retryUntilメソッドでタイムアウトする時刻を\DateTimeで返します。

class MyListener implements ShouldQueue
{
    /**
     * 処理失敗時の最大試行回数
     * 初期値は1
     */
   public $tries = 5;

   /**
    * リスナーがタイムアウトする時刻を設定
    *
    * @return \DateTime
    */
    public function retryUntil()
    {
        return now()->addMinutes(5);
    }
}

ジョブを送信するのに使用する接続名はpublic $connectionに、キュー名はpublic $queueに、ジョブを処理するまでの遅延時間はpublic $delayに設定します。

接続名は、app/config/queue.phpにあります。

class MyListener implements ShouldQueue
{
    public $connection = 'database';

    public $queue = 'hogehoge';

    // キューが登録されてから $delay 秒後にジョブが実行される
    public $delay = 10;
}

キュー名がどのように使用されるかは接続先によります。databaseの場合、queueカラムに入ります。

queue設定時に反映されるカラム

まとめ

イベントをキューに入れて動作させるには、implements ShouldQueueを実装します。キューに入れることでメインロジックとは切り離して非同期でジョブを実行させることが可能です。

キューイングの基礎知識も取り入れつつ使っていきましょう。

laravel event queue thumb

役に立ったらシェアしよう!