【Laravel】 イベントのリスナーにキューを使用する方法
イベントを実行する際、時間のかかるイベントを実行したい場合があります。しかし、普通に同期で処理していてはその後の処理に響いてしまいます。そこで、イベントにキューを使用して裏で実行できるようにしてみましょう。
基本的なイベントについては、下の記事を確認してください。
キューを使ったイベント
通常のイベントは同期で処理されます。しかし、例えばHTTP通信をするなど、長時間かかる可能性がある処理はキューを用いて非同期で実行させることができます。
キューイングシステムの設定はconfig/queue.php
にあります。
基本的な構造は同じで、リスナー側にShouldQueue
を実装します。
class MyListener implements ShouldQueue { // ... }
あとは普通のイベントと同様に投げるだけです。これで非同期でイベントを処理できるようになり、重い処理を裏で、あるいは後で行うといったことが可能になります。
デフォルトでは同期で動作するため、裏で動かすようにしたい場合は設定を変更する必要があります。
キューでのイベントを試したいだけの場合、.env
のQUEUE_CONNECTION
の値をdatabase
に書き換え、php artisan queue:table
とphp 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
カラムに入ります。

まとめ
イベントをキューに入れて動作させるには、implements ShouldQueue
を実装します。キューに入れることでメインロジックとは切り離して非同期でジョブを実行させることが可能です。
キューイングの基礎知識も取り入れつつ使っていきましょう。
