From 3dd5311430226031664c04108277e1512863affd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E6=9E=97?= Date: Tue, 11 Oct 2022 14:33:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=98=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 1 + kiri-actor/Actor.php | 136 ++++++++++++++++++++++++++++++++++ kiri-actor/ActorInterface.php | 14 ++++ kiri-actor/ActorManager.php | 97 ++++++++++++++++++++++++ kiri-actor/ActorProcess.php | 81 ++++++++++++++++++++ kiri-actor/ActorState.php | 15 ++++ 6 files changed, 344 insertions(+) create mode 100644 kiri-actor/Actor.php create mode 100644 kiri-actor/ActorInterface.php create mode 100644 kiri-actor/ActorManager.php create mode 100644 kiri-actor/ActorProcess.php create mode 100644 kiri-actor/ActorState.php diff --git a/composer.json b/composer.json index f4cfefea..a3a03e80 100644 --- a/composer.json +++ b/composer.json @@ -33,6 +33,7 @@ "autoload": { "psr-4": { "Kiri\\": "kiri-engine/", + "Kiri\\Actor\\": "kiri-actor/", "Kiri\\Annotation\\": "kiri-annotation/", "Kiri\\Task\\": "kiri-task/" }, diff --git a/kiri-actor/Actor.php b/kiri-actor/Actor.php new file mode 100644 index 00000000..80f40714 --- /dev/null +++ b/kiri-actor/Actor.php @@ -0,0 +1,136 @@ +state; + } + + + /** + * @param ActorState $state + */ + public function setState(ActorState $state): void + { + $this->state = $state; + } + + + /** + * @return float + */ + public function getRunTime(): float + { + return microtime(true) - $this->startTime; + } + + + /** + * @param string $uniqueId + */ + private function __construct(readonly public string $uniqueId) + { + $this->channel = new Channel(1000); + $this->startTime = microtime(true); + } + + + /** + * @param $id + * @return static + */ + public static function newActor($id): static + { + return new static($id); + } + + + /** + * @return string + */ + public function getName(): string + { + return $this->uniqueId; + } + + + /** + * @param mixed $response + * @return bool + */ + public function write(mixed $response): bool + { + return $this->channel->push($response); + } + + + /** + * @return void + */ + public function shutdown(): void + { + $this->isShutdown = true; + $this->channel->close(); + } + + + /** + * @return void + */ + public function run(): void + { + if ($this->channel->errCode == SWOOLE_CHANNEL_CLOSED) { + if ($this->isShutdown) { + return; + } + $this->channel = new Channel(1000); + } + $this->setState(ActorState::BUSY); + while (!$this->isShutdown) { + $message = $this->channel->pop(); + $this->process($message); + unset($message); + } + $this->setState(ActorState::IDLE); + if ($this->isShutdown) { + $this->channel->close(); + return; + } + $this->run(); + } + +} diff --git a/kiri-actor/ActorInterface.php b/kiri-actor/ActorInterface.php new file mode 100644 index 00000000..3161f2fe --- /dev/null +++ b/kiri-actor/ActorInterface.php @@ -0,0 +1,14 @@ + */ + private array $nodes = []; + + + /** + * @param Actor $actor + * @return void + */ + public function addActor(ActorInterface $actor): void + { + $this->nodes[$actor->uniqueId] = $actor; + Coroutine::create(function (Actor $actor) { + $actor->run(); + }, $actor); + } + + + /** + * @param $name + * @return void + */ + public function closeActor($name): void + { + $node = $this->nodes[$name] ?? null; + if (is_null($node)) { + return; + } + foreach ($node as $actor) { + $actor->shutdown(); + } + } + + + /** + * @param $name + * @param $message + * @return bool + */ + public function write($name, $message): bool + { + $actor = $this->nodes[$name] ?? null; + if (is_null($actor)) { + return false; + } + return $actor->write($message); + } + + + /** + * @param $name + * @return array + */ + public function lists($name): array + { + $array = []; + foreach ($this->nodes[$name] as $actor) { + $array[] = [ + 'id' => $actor->getName(), + 'state' => $actor->getState()->name, + 'runTime' => $actor->getRunTime() + ]; + } + return $array; + } + + + /** + * @param string $uniqueId + * @return bool + */ + public function hasActor(string $uniqueId): bool + { + return isset($this->nodes[$uniqueId]) && $this->nodes[$uniqueId] instanceof ActorInterface; + } + + + /** + * @return void + */ + public function clean(): void + { + foreach ($this->nodes as $actor) { + $actor->shutdown(); + } + $this->nodes = []; + } + +} diff --git a/kiri-actor/ActorProcess.php b/kiri-actor/ActorProcess.php new file mode 100644 index 00000000..b9941e11 --- /dev/null +++ b/kiri-actor/ActorProcess.php @@ -0,0 +1,81 @@ +container->get(ActorManager::class); + while (!$this->isStop()) { + $read = json_decode($process->read(), true); + if (is_null($read) || !isset($read['event'])) { + continue; + } + switch ($read['event']) { + case ActorState::MESSAGE: + $actorManager->write($read['name'], $read['message']); + break; + case ActorState::CREATE: + /** @var ActorInterface $actor */ + $actor = $this->container->create($read['class']); + $actorManager->addActor($actor); + break; + case ActorState::SHUTDOWN: + $actorManager->closeActor($read['name']); + break; + } + } + } + + + /** + * @return $this + */ + public function onSigterm(): static + { + pcntl_signal(SIGTERM, function () { + $this->onProcessStop(); + }); + return $this; + } + +} diff --git a/kiri-actor/ActorState.php b/kiri-actor/ActorState.php new file mode 100644 index 00000000..9391ccc5 --- /dev/null +++ b/kiri-actor/ActorState.php @@ -0,0 +1,15 @@ +