Laravel

queue:work --daemon をきちんと動かしてみる

More than 3 years have passed since last update.

laravel の queue を daemon で動かすにはぐぐってみると supervisor を使っている事例が多く見つかる。

しかし、queue:listen (または queue:work --daemon) が pop した worker job を処理している最中でも、遠慮なく SIG* で終了させてしまう実装になっているように見えるため、タイミングによっては worker job が適切に完了されない場合もある。

ちなみに laravel の queue は 4.2 の実装では 2 種類存在する。

ただし、後者は worker job が終了する毎に queue:restart で終了命令が発行されていないか確認して、されている場合は queue:work --daemon 自身を終了するようになっている。

そこで queue:restart を使って、実行中かもしれない worker job を SIG* で強制終了させることなく queue:work --daemon を再起動させる仕組みを考えてみた。

laravel の Command の fire() で以下の実装をしてみる。


start.php

$pidFile = '/var/run/laravel-queue-work-daemon.pid';

if (File::exists($pidFile)) {
return;
}

$pid = pcntl_fork();

if ($pid === -1) {
exit();
} elseif ($pid !== 0) {
exit();
} else {
posix_setsid();
File::append($pidFile, posix_getpid() . PHP_EOL);
$this->call('queue:work', [
'--daemon' => true
]);
}



stop.php

$pidFile = '/var/run/laravel-queue-work-daemon.pid';

if (! File::exists($pidFile)) {
return;
}

$pid = intval(File::get($pidFile));

$this->call('queue:restart');

$procPath = '/proc/' . $pid;
while (true) {
if (! File::exists($procPath)) {
break;
}
sleep(1);
}

File::delete($pidFile);


これで daemon を起動する時は



% /usr/bin/nohup php artisan myqueue:start < /dev/null > /dev/null 2>&1 &



終わらせる時は



% php artisan myqueue:stop



とそれぞれ入力すればいい。