Last active
May 4, 2018 08:49
-
-
Save cmizzi/4443aa4bfee68cea9695bfa41890acd2 to your computer and use it in GitHub Desktop.
Laravel daemon command
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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