Laravelのキューはオプションとモードによって動作が異なります。今回ハマったのですが、メンテナンスモードだとキューが実行されません。

環境


お約束の環境ですがLaravel 5.5です。

結論


先に結論を書いておくと、下記のような感じです。

  • Laravelのキューはonceオプションをつけないとdaemonモードで動作する
  • daemonモードはメンテナンスモードだととキュー実行しない
  • メンテナンスモードでもキュー実行させるには--forceオプションを使う

メンテナンスモードとは…?


LaravelにはMaintenance Modeというものが存在し、下記のコマンドでメンテナンスモードに設定することが可能です。メンテナンスモードにするとIP制限が容易になり、キューも実行されなくなります。

1
php artisan down

このモードは下記のコマンドで解消することが可能です。

1
php artisan up

コードを見てみる


実際にコードを見てみましょう。Laravelのキューは実行時に\Illuminate\Queue\Console\WorkCommandというクラスのhandleメソッドを呼び出しています。

このhandleメソッドの中ではrunWorkerメソッドというのを呼び出しています。このメソッドの中でさらにonceの場合は\Illuminate\Queue\WorkerクラスのrunNextJobを呼び出しており、そうでない場合はdaemonメソッドを呼び出しています。

1
2
3
4
5
6
7
8
protected function runWorker($connection, $queue)
{
$this->worker->setCache($this->laravel['cache']->driver());

return $this->worker->{$this->option('once') ? 'runNextJob' : 'daemon'}(
$connection, $queue, $this->gatherWorkerOptions()
);
}

※Laravelのコードより

実際の運用ではonceで実行している場合は少ないと思いますので、それ以外のモードで実行している前提として話を進めます。

では、Workerクラスのdaemonメソッドとは何をしているのでしょうか?それが下記です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function daemon($connectionName, $queue, WorkerOptions $options)
{
$this->listenForSignals();

$lastRestart = $this->getTimestampOfLastQueueRestart();

while (true) {
// Before reserving any jobs, we will make sure this queue is not paused and
// if it is we will just pause this worker for a given amount of time and
// make sure we do not need to kill this worker process off completely.
if (! $this->daemonShouldRun($options, $connectionName, $queue)) {
$this->pauseWorker($options, $lastRestart);

continue;
}
...以下略

※Laravelのコードより

daemonShouldRunとはなにをしているのでしょうか?見てみましょう。

1
2
3
4
5
6
protected function daemonShouldRun(WorkerOptions $options, $connectionName, $queue)
{
return ! (($this->manager->isDownForMaintenance() && ! $options->force) ||
$this->paused ||
$this->events->until(new Events\Looping($connectionName, $queue)) === false);
}

※Laravelのコードより

ああ!!isDownForMaintenanceつまり、メンテナンスモードと--forceオプションが付いていない場合はfalseを返すんですね!!

つまり、メンテナンスモードでonceオプションを付与しない場合だと、forceオプションを付与しない限りキューは実行されないということになります。

で?結論は?


記事の頭にも書いているのですが、下記のような感じになります。

  • キュー実行時にonceを付与していないとdaemonモードで動く
  • daemonモードはメンテナンスモードだととキュー実行しない
  • メンテナンスモードでもキュー実行させるには--forceオプションを使う

こんな感じです。ですので、メンテナンスモードでonce以外でキュー実行させたいのであれば--forceオプションを付与して実行しましょう。

前回の件もあるのですが、こんなのちゃんとログで出して欲しいんですよ。 ドキュメントをさっと見た感じですが、メンテナンスモードで実行されない旨は書かれてないですし すみません。書いてありました…。申し訳なさの極み。 せめてログにちゃんと出して欲しいんですよ。わかります???この気持ち。こんなとこまで言語のゆるふわを引き継がなくていんですよ。わかります??マジムカ着火ファイヤーだょ…