<?php
namespace App\Console\Commands;
use App\Services\Topics;
use Illuminate\Console\Command;
use PhpSpec\Exception\Exception;
use Symfony\Component\Console\Input\InputOption;
/**
* @brief content
* @author weihaoyu
* @createdAt date
* @updatedAt date
* @version 1.0
*/
class RedisQueueConsumer extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $name = 'why:redis_queue_consumer';
protected $logName = 'redis_queue_consumer.log';
private $sigalrm = 5;
private $nowId;
private $redis;
/**
* The console command description.
*
* @var string
*/
protected $description = '每天处理更新每个专题的问题补全,并生成静态html';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->redis = new \Redis();
$this->redis->connect(env('REDIS_LIMIT_HOST'), env('REDIS_LIMIT_PORT'));
$this->redis->auth(env('REDIS_LIMIT_PASSWORD'));
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
try{
$queue = $this->option('queue');
if(empty($queue)){
$this->writeLog('no queue name');
die;
}
$this->nowId = $id;
$sigalrm = $this->option('sigalrm');
if(!empty($sigalrm)){
$this->sigalrm = $sigalrm;
}
$this->listenForSignals();
while (true){
$this->registerTimeoutHandler();
$id = $this->redis->rpoplpush($queue, $queue . '_fail');
if(empty($id)){
$this->writeLog('queue empty, exit');
exit;
}
$length = Topics::createHtmlFile((int)$id, base_path() . '/public/topics/');
if($length > 0){
$this->redis->rpop($queue.'_fail');
$this->writeLog($this->nowId . '-write ' .$length. ' success');
}else{
$this->writeLog($this->nowId . '-write ' .$length. ' fail');
}
}
}catch (Exception $e){
echo $e->getCode() . "\n";
echo $e->getMessage() . "\n";
}
}
protected function registerTimeoutHandler()
{
if ($this->supportsAsyncSignals()) {
pcntl_signal(SIGALRM, function () {
$msg = $this->nowId . '-timeout';
$this->writeLog($msg);
});
pcntl_alarm($this->sigalrm);
}
}
protected function writeLog($msg)
{
$str = date('Y-m-d H:i:s', time()) . ':' . $msg . "\n";
file_put_contents(storage_path() . '/logs/' . $this->logName, $str, FILE_APPEND);
}
protected function listenForSignals()
{
if ($this->supportsAsyncSignals()) {
pcntl_async_signals(true);
}
}
protected function supportsAsyncSignals()
{
return version_compare(PHP_VERSION, '7.1.0') >= 0 && extension_loaded('pcntl');
}
protected function getOptions()
{
return array(
array('queue', null, InputOption::VALUE_REQUIRED, 'queue name', null),
array('sigalrm', null, InputOption::VALUE_REQUIRED, 'sigalrm time', null),
);
}
public function __destruct()
{
$this->redis->close();
}
}