I recently setup a Laravel Queue system. The basics are a cronjob calls a command which adds jobs to a queue and calls a second command which sends an email.
The sy
I achieved the result without any service monitor or third party software. The solution is working fine but I am not sure if it is the best way.
Solution
Just run cli command in the following way in your function.
use Illuminate\Console\Command;
public function callQueue()
{
$restart = 'php-cli ' . base_path() . '/artisan queue:restart > /dev/null & echo $!';
$work = 'php-cli ' . base_path() . '/artisan queue:work --timeout=0 --sleep=5 --tries=3 > /dev/null & echo $!';
exec($restart);
exec($work);
}
$job = (new jobName())->delay(Carbon::now()->addSeconds(5));
dispatch($job);
Reason
The reason I have used these two commands is because the command associated with $restart
prevent having any memory issue according to a comment in this answer
and the command associated with $work
ensures that the command is successfully executed before the job.
The command
nohup php artisan queue:work --daemon &
was correct, it would allow the process to continue after closing the SSH connection; however, this is only a short term fix. Once your server is rebooted or any issue causes the process to stop you will need to go back and run the command again. When that occurs, you never know. It could happen on a Friday night, so it is better to implement a long term solution.
I ended up switching over to Supervisord, this can be installed on Ubuntu as easy as
sudo apt-get install supervisor
For AWS-AMI or RedHat users you can follow the set of instructions I outlined in this question:
Setting up Supervisord on a AWS AMI Linux Server
What if you start the listening within a screen? See here: http://aperiodic.net/screen/quick_reference Then even if you log out, the screen would still be active and running. Not sure why the daemonization doesnt work though.
From https://gist.github.com/ivanvermeyen/b72061c5d70c61e86875
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class EnsureQueueListenerIsRunning extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'queue:checkup';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Ensure that the queue listener is running.';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
if ( ! $this->isQueueListenerRunning()) {
$this->comment('Queue listener is being started.');
$pid = $this->startQueueListener();
$this->saveQueueListenerPID($pid);
}
$this->comment('Queue listener is running.');
}
/**
* Check if the queue listener is running.
*
* @return bool
*/
private function isQueueListenerRunning()
{
if ( ! $pid = $this->getLastQueueListenerPID()) {
return false;
}
$process = exec("ps -p $pid -opid=,cmd=");
//$processIsQueueListener = str_contains($process, 'queue:listen'); // 5.1
$processIsQueueListener = ! empty($process); // 5.6 - see comments
return $processIsQueueListener;
}
/**
* Get any existing queue listener PID.
*
* @return bool|string
*/
private function getLastQueueListenerPID()
{
if ( ! file_exists(__DIR__ . '/queue.pid')) {
return false;
}
return file_get_contents(__DIR__ . '/queue.pid');
}
/**
* Save the queue listener PID to a file.
*
* @param $pid
*
* @return void
*/
private function saveQueueListenerPID($pid)
{
file_put_contents(__DIR__ . '/queue.pid', $pid);
}
/**
* Start the queue listener.
*
* @return int
*/
private function startQueueListener()
{
//$command = 'php-cli ' . base_path() . '/artisan queue:listen --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.1
$command = 'php-cli ' . base_path() . '/artisan queue:work --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.6 - see comments
$pid = exec($command);
return $pid;
}
}
For systems with systemd as init service you could use the following service, adapting it to your project (create it on /etc/systemd/system/queue-handler.service):
[Unit]
Description = Queue Handler - Project
After = network-online.target, mysql.service
[Service]
User = www-data
Type = simple
WorkingDirectory=/var/www/project
ExecStart = /usr/bin/php /var/www/project/artisan queue:work --tries=3
Restart = on-failure
RestartSec=5s
RestartPreventExitStatus = 255
[Install]
WantedBy = multi-user.target
Reload the configurations and enable it on boot:
$ systemctl enable queue-handler.service
$ systemctl daemon-reload