ヒエラルキー構造を利用してみよう
次にアクターモデルの特徴であるヒエラルキー構造を利用してみましょう。
HelloActorを親アクターとして、WorldActorを子アクターとして生成し、WorldActorにHelloResponseメッセージに関する処理を担当してもらうようにします。
次のようなWorldActorクラスを作成します。
<?php declare(strict_types=1); namespace Sample; use Phluxor\ActorSystem\Context\ContextInterface; use Phluxor\ActorSystem\Message\ActorInterface; class WorldActor implements ActorInterface { public function receive(ContextInterface $context): void { $message = $context->message(); if ($message instanceof Message\HelloRequest) { $response = new Message\HelloResponse('Hello Child, ' . $message->message); $context->respond($response); } } }
WorldActorはHelloRequestメッセージを受信した場合にHelloResponseメッセージを作成し、送信元に返信する処理を行います。
次にHelloActorを親アクターとしてWorldActorを生成するように変更します。
<?php declare(strict_types=1); namespace Sample; use Phluxor\ActorSystem\Context\ContextInterface; use Phluxor\ActorSystem\Message\ActorInterface; use Phluxor\ActorSystem\Props; use Phluxor\ActorSystem\Ref; class HelloActor implements ActorInterface { private ?Ref $sender = null; public function receive(ContextInterface $context): void { $message = $context->message(); switch (true) { case $message instanceof Message\HelloRequest: $this->sender = $context->sender(); $ref = $context->spawn( Props::fromProducer(fn() => new WorldActor()) ); $context->request($ref, $message); break; case $message instanceof Message\HelloResponse: $context->send($this->sender, $message); break; } } }
HelloActorはHelloRequestメッセージを受信した場合に、子アクターとしてWorldActorを生成しHelloRequestメッセージを送信します。
子アクターであるWorldActorでHelloResponseメッセージを作成し、HelloActorに返信するように変更したので、HelloResponseメッセージを受信した場合には送信元にHelloResponseメッセージを送信します。
このときアクターのヒエラルキー構造は次のようになります。
これまでのコード例の場合は実際には$1/$3
のような形でヒエラルキー構造を持ち、名前は自動で生成されますが、spawnNamed
メソッドを利用することで図と同一のアクター構造を生成することも可能です。
その場合はユニークな名前を指定することが必須となりますので、名前の重複に注意して利用するようにしてください。
アクターのコンテキストには誰からメッセージが送信されたかが含まれています。
このヒエラルキー構造からわかるように、HelloActorはWorldActorやFutureからメッセージを受信していますので、最初に送られてきたSenderの情報を保持しておくことで、HelloResponseメッセージを送信元に返信できます。
アクターは状態を共有することはありませんので、このようにアクター毎に情報を保持できます。
なおrespond
は直前の送信元に返信するためのメソッドのため、ここではsend
メソッドを利用して送信先を指定し返信を行っています。
このコードをコンソールなどから実行すると下記のように表示されます。