Skip to content

Instantly share code, notes, and snippets.

@cmizzi
Last active May 4, 2018 08:49
Show Gist options
  • Save cmizzi/4443aa4bfee68cea9695bfa41890acd2 to your computer and use it in GitHub Desktop.
Save cmizzi/4443aa4bfee68cea9695bfa41890acd2 to your computer and use it in GitHub Desktop.
Laravel daemon command
<?php
declare(strict_types=1);
declare(ticks=1);
namespace App\Console;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
abstract class DaemonCommand extends Command {
/** @var bool $stopRequested */
private $stopRequested = false;
/**
* Daemonize command
*
* @return void
*/
private function daemonize() {
ini_set('max_execution_time', '0');
pcntl_signal(SIGTERM, [$this, 'handleSignals']);
pcntl_signal(SIGINT, [$this, 'handleSignals']);
$this->info("Process PID - " . getmypid());
}
/**
* Returns true if the process should be stopped
*
* @return bool
*/
protected function shouldStopRunning(): bool {
return $this->stopRequested;
}
/**
* Sleep by step
*
* @param int $seconds
* @return void
*/
protected function sleep(int $seconds) {
$uSeconds = $seconds * 1000000;
$interval = 100000;
$total = 0;
while ($total < $uSeconds and !$this->stopRequested) {
$total += $interaval;
usleep($interval);
}
}
/**
* Handle signals
*
* @param int $signal
* @return void
*/
protected function handleSignals(int $signal) {
switch ($signal) {
case SIGTERM :
case SIGINT :
$this->info("Received signal, will stop ASAP (code {$signal})");
$this->stopRequested = true;
default :
$this->info("Received signal, ignored (code {$signal})");
break;
}
}
/**
* {@inheritDoc}
*
* @param InputInterface $input
* @param OutputInterface $output
* @return void
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$this->daemonize();
try {
parent::execute($input, $output);
} catch (\Exception $e) {
$this->error($e);
}
}
}
// Now, you can implement this class like following
<?php
declare(strict_types=1);
namespace App\Console\Commands;
use App\Console\DaemonCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MyDaemonizedCommand extends DaemonCommand {
/**
* Handle command
*
* @return void
*/
public function handle() {
while (!$this->shouldStopRunning()) {
try {
// You code go here
//
// If something failed, you can call the `sleep` method instead
// of function in order to keep `stopRequested` working
}
catch (\Exception $e) {
$this->error($e);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment