diff --git a/Kafka/Producer.php b/Kafka/Producer.php index 36e9877d..34ee0797 100644 --- a/Kafka/Producer.php +++ b/Kafka/Producer.php @@ -10,10 +10,7 @@ use RdKafka\TopicConf; use ReflectionException; use Snowflake\Abstracts\Component; use Snowflake\Abstracts\Config; -use Snowflake\Core\Json; use Snowflake\Event; -use Snowflake\Exception\ComponentException; -use Snowflake\Exception\ConfigException; use Snowflake\Exception\NotFindClassException; use Snowflake\Snowflake; diff --git a/System/Abstracts/BaseApplication.php b/System/Abstracts/BaseApplication.php index 7c2543aa..28a04e6e 100644 --- a/System/Abstracts/BaseApplication.php +++ b/System/Abstracts/BaseApplication.php @@ -448,27 +448,27 @@ abstract class BaseApplication extends Service protected function moreComponents(): void { $this->setComponents([ - 'error' => ['class' => ErrorHandler::class], - 'event' => ['class' => Event::class], - 'connections' => ['class' => Connection::class], - 'redis_connections' => ['class' => SRedis::class], - 'pool' => ['class' => SPool::class], - 'response' => ['class' => Response::class], - 'request' => ['class' => Request::class], - 'config' => ['class' => Config::class], - 'logger' => ['class' => Logger::class], - 'attributes' => ['class' => SAnnotation::class], - 'router' => ['class' => Router::class], - 'redis' => ['class' => Redis::class], - 'jwt' => ['class' => Jwt::class], - 'async' => ['class' => Async::class], - 'filter' => ['class' => HttpFilter::class], - 'crontab' => ['class' => Crontab::class], - 'object' => ['class' => ObjectPool::class], - 'goto' => ['class' => BaseGoto::class], - 'rpc' => ['class' => \Rpc\Producer::class], - 'rpc-service' => ['class' => \Rpc\Service::class], - 'http2' => ['class' => Http2::class], + 'error' => ['class' => ErrorHandler::class], + 'event' => ['class' => Event::class], + 'connections' => ['class' => Connection::class], + 'redis_connections' => ['class' => SRedis::class], + 'pool' => ['class' => SPool::class], + 'response' => ['class' => Response::class], + 'request' => ['class' => Request::class], + 'config' => ['class' => Config::class], + 'logger' => ['class' => Logger::class], + 'attributes' => ['class' => SAnnotation::class], + 'router' => ['class' => Router::class], + 'redis' => ['class' => Redis::class], + 'jwt' => ['class' => Jwt::class], + 'async' => ['class' => Async::class], + 'filter' => ['class' => HttpFilter::class], + 'crontab' => ['class' => \Snowflake\Crontab\Producer::class], + 'object' => ['class' => ObjectPool::class], + 'goto' => ['class' => BaseGoto::class], + 'rpc' => ['class' => \Rpc\Producer::class], + 'rpc-service' => ['class' => \Rpc\Service::class], + 'http2' => ['class' => Http2::class], ]); } } diff --git a/System/Abstracts/TraitApplication.php b/System/Abstracts/TraitApplication.php index f773e892..58505de4 100644 --- a/System/Abstracts/TraitApplication.php +++ b/System/Abstracts/TraitApplication.php @@ -45,7 +45,7 @@ use Rpc\Producer as RPCProducer; * @property Producer $kafka * @property Client $client * @property Curl $curl - * @property Crontab $crontab + * @property \Snowflake\Crontab\Producer $crontab * @property HttpFilter $filter * @property RPCProducer $rpc */ diff --git a/System/Crontab/Consumer.php b/System/Crontab/Consumer.php new file mode 100644 index 00000000..a391b5d6 --- /dev/null +++ b/System/Crontab/Consumer.php @@ -0,0 +1,82 @@ +getRedis(); + + $process->name('Crontab consumer'); + + while (true) { + [$value, $startTime] = swoole_unserialize($process->read()); + + $crontab = $redis->get('crontab:' . md5($value)); + $redis->del('crontab:' . md5($value)); + if (empty($crontab) || !($crontab = swoole_unserialize($crontab))) { + continue; + } + + Coroutine::create(function (Crontab $value, int $startTime) { + $this->dispatch($value); + }, $crontab, $startTime); + } + } + + + /** + * @param Crontab $value + * @throws Exception + */ + private function dispatch(Crontab $value) + { + $value->increment()->execute(); + if ($value->getExecuteNumber() < $value->getMaxExecuteNumber()) { + $this->addTask($value); + } else if ($value->isLoop()) { + $this->addTask($value); + } + fire(Event::SYSTEM_RESOURCE_RELEASES); + } + + + /** + * @param Crontab $crontab + * @throws Exception + */ + private function addTask(Crontab $crontab) + { + $redis = Snowflake::app()->getRedis(); + + $name = md5($crontab->getName()); + + $redis->set('crontab:' . $name, swoole_serialize($crontab)); + + $tickTime = time() + $crontab->getTickTime(); + + $redis->zAdd(Producer::CRONTAB_KEY, $tickTime, $crontab->getName()); + } + + +} diff --git a/System/Crontab.php b/System/Crontab/Crontab.php similarity index 98% rename from System/Crontab.php rename to System/Crontab/Crontab.php index ca17f078..a8162368 100644 --- a/System/Crontab.php +++ b/System/Crontab/Crontab.php @@ -1,13 +1,13 @@ get('crontab'); + $crontab->clearAll(); + + $process->name('Crontab zookeeper.'); + Timer::tick(1000, function () { + $startTime = time(); + + $redis = Snowflake::app()->getRedis(); + + $range = $redis->zRangeByScore(Producer::CRONTAB_KEY, '0', (string)$startTime); + $redis->zRemRangeByScore(Producer::CRONTAB_KEY, '0', (string)$startTime); + + /** @var Consumer $consumer */ + $consumer = Snowflake::app()->get(Consumer::class); + + foreach ($range as $value) { + $consumer->write(swoole_serialize(['crontab:' . md5($value), $startTime])); + } + $redis->release(); + }); + } + + + /** + * @param string $name + */ + public function clear(string $name) + { + if (!isset($this->names[$name])) { + return; + } + $timers = $this->timers[$name]; + + $search = array_search($name, $this->scores[$timers]); + if ($search !== false) { + unset($this->scores[$timers][$search]); + } + unset($this->timers[$name], $this->names[$name]); + } + + +} diff --git a/System/Abstracts/Crontab.php b/System/Crontab/Producer.php similarity index 82% rename from System/Abstracts/Crontab.php rename to System/Crontab/Producer.php index cc82dcd1..5f0f1c1c 100644 --- a/System/Abstracts/Crontab.php +++ b/System/Crontab/Producer.php @@ -1,31 +1,30 @@ getRedis(); diff --git a/System/Process/CrontabProcess.php b/System/Process/CrontabProcess.php deleted file mode 100644 index d1e96dd8..00000000 --- a/System/Process/CrontabProcess.php +++ /dev/null @@ -1,125 +0,0 @@ -get('crontab'); - $crontab->clearAll(); - - Timer::tick(1000, function () { - $startTime = time(); - - $redis = Snowflake::app()->getRedis(); - - $range = $redis->zRangeByScore(ACrontab::CRONTAB_KEY, '0', (string)$startTime); - $redis->zRemRangeByScore(ACrontab::CRONTAB_KEY, '0', (string)$startTime); - foreach ($range as $value) { - $crontab = $redis->get('crontab:' . md5($value)); - $redis->del('crontab:' . md5($value)); - if (empty($crontab) || !($crontab = swoole_unserialize($crontab))) { - continue; - } - Coroutine::create(function (Crontab $value, int $startTime) { - $this->dispatch($value); - }, $crontab, $startTime); - } - $redis->release(); - }); - } - - - /** - * @param Crontab $value - * @throws Exception - */ - private function dispatch(Crontab $value) - { - $value->increment()->execute(); - if ($value->getExecuteNumber() < $value->getMaxExecuteNumber()) { - $this->addTask($value); - } else if ($value->isLoop()) { - $this->addTask($value); - } - fire(Event::SYSTEM_RESOURCE_RELEASES); - } - - - /** - * @param string $name - */ - public function clear(string $name) - { - if (!isset($this->names[$name])) { - return; - } - $timers = $this->timers[$name]; - - $search = array_search($name, $this->scores[$timers]); - if ($search !== false) { - unset($this->scores[$timers][$search]); - } - unset($this->timers[$name], $this->names[$name]); - } - - - /** - * @param Crontab $crontab - * @throws Exception - */ - private function addTask(Crontab $crontab) - { - $redis = Snowflake::app()->getRedis(); - - $name = md5($crontab->getName()); - - $redis->set('crontab:' . $name, swoole_serialize($crontab)); - - $tickTime = time() + $crontab->getTickTime(); - - $redis->zAdd(ACrontab::CRONTAB_KEY, $tickTime, $crontab->getName()); - } - - -}