Laravel の QUEUE_CONNECTION=sync について確認してみた
Laravel のキュー処理の接続設定について、database(リレーショナルデータベース)、redis(Redis)、beanstalkd(Beanstalk)、sqs(Amazon SQS)と null(キューされたジョブを破棄して実行しない)は感覚的にわかるのですが、デフォルトで設定されている sync についてピンと来なかったので、ソースを確認してみました。
結果:キューに入れて即実行
sync を設定したときの挙動については、Illuminate/Queue/SyncQueue に記載されているのですが、キューに投入されたときには push メソッドが呼び出されます。該当部分を引用すると
public function push($job, $data = '', $queue = null)
{
$queueJob = $this->resolveJob($this->createPayload($job, $queue, $data), $queue);
try {
$this->raiseBeforeJobEvent($queueJob);
$queueJob->fire();
$this->raiseAfterJobEvent($queueJob);
} catch (Throwable $e) {
$this->handleException($queueJob, $e);
}
return 0;
}
こんな感じ。キューを作成して、すぐに fire() でジョブが実行されていることがわかります。Laravel の日本語ドキュメントにも
ジョブが即時に実行される同期(ローカル用途)ドライバーが含まれています
https://readouble.com/laravel/6.x/ja/queues.html
と記載されていますが、その通りの挙動になっています(同期ドライバー= sync のことです)。
QUEUE_CONNECTION=sync の使い道
QUEUE_CONNECTION=sync 以外の設定をする場合、データベースや Redis の設定をしたり、ワーカの監視のために Supervisor を設定したりと、割と面倒です。本番環境であれば本気で(?)設定しますが、ローカル環境で動作確認するにはちょっと荷が重いです。そんなときに QUEUE_CONNECTION=sync を .env に設定しておくことで、このあたりの手間を省くことができます。
具体的には、「問い合わせフォーム→メール送信処理→完了画面」みたいな処理をする場合に、メール送信処理を待っていると、フォームの送信ボタンを押してから完了画面の表示まで数秒待たされるので、メール送信処理をキューに入れて非同期処理することって多いと思います。これを「本番環境ならキューに入れ、ローカルでは即時送信」と処理を分けようとすると、
if (config('app.env') != 'production') {
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->send(new OrderShipped($order));
} else {
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue(new OrderShipped($order));
}
こんな感じで書くことになりますが、QUEUE_CONNECTION=sync があることで
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue(new OrderShipped($order));
だけでどちらにも対応できるようになります。単純にコードが短くなるだけでなく、環境設定のミスで思わぬ挙動で悩むことを防げます。
また、config/queue.php
で 'default' => env('QUEUE_CONNECTION', 'sync'),
となっているので、.env で QUEUE_CONNECTION を設定してなくても、 sync で設定されます。コードを Git から pull した直後でも Laravel が動作する環境さえ作っておけば、アプリがきちんと動作するわけです。このあたり、親切にできてるな、と改めて思ったのでした。
ディスカッション
コメント一覧
まだ、コメントがありません