This is a design question;
Say I have a tree of actors which do a bunch of processing. The processing is kicked off by a client/connection actor (i.e. the tree is the server). Eventually the client actor wants a response. I.e. I have an actor system that looks like this.
ActorA <---reqData--- Client_Actor
| msgA /|\
\|/ |
ActorB |
msgB | \ msgD |
\|/ \/ |
ActorC ActorD---------msgY-->|
|_____________msgX_________|
The response that the client system wants is the output from the leaf actors (i.e. ActorC
and/or ActorD
). These actors in the tree may be interacting with external systems. This tree may be a set of pre-defined possibly routed actors (i.e. so Client_actor
just has a actorref to the root of the actor tree, ActorA
).
The question is what is the best pattern to manage sending the response (msgX
&/or msgY
) from the final/leaf actors back to the client actor?
I can think of the following options;
msgX
or msgY
, send it back to the original sender ref so the messages are passed back up through the tree. I.e each actor will keep a ref of the original sender. Client_Actor
ref in the reqData
message and replicate this for all messages used in the tree so the leaf actors can reply directly to the Client_actor
... This seems like the most performant option. Not sure how to do this (I'm thinking a trait somehow on the message case classes that holds the client actor ref)...FYI I'm using Akka 2.2.1.
Cheers!
1) Akka Actor tell() Method It works on "fire-forget" approach. You can also use ! (bang) exclamation mark to send message. This is the preferred way of sending messages.
In Akka, you can stop Actors by invoking the stop() method of either ActorContext or ActorSystem class. ActorContext is used to stop child actor and ActorSystem is used to stop top level Actor. The actual termination of the actor is performed asynchronously.
Companion object ActorSystem An actor system is a hierarchical group of actors which share common configuration, e.g. dispatchers, deployments, remote capabilities and addresses. It is also the entry point for creating or looking up actors. There are several possibilities for creating actors (see akka.
Akka's approach to handling concurrency is based on the Actor Model. In an actor-based system, everything is an actor, in much the same way that everything is an object in object-oriented design.
You could use the forward
method to forward the message from the original sender to the child sender at each level.
in Client_Actor:
actorA ! "hello"
in ActorA:
def receive = {
case msg =>
???
actorB forward msg
}
in ActorB:
def receive = {
case msg =>
???
actorC forward msg
}
in ActorC:
def receive = {
case msg =>
???
sender ! "reply" // sender is Client_Actor!
}
In this case, the 'sender' field of the message will never change, so ActorC will reply to the original Client_Actor!
You can extend this further by using the tell
method variant that lets you specify the sender:
destinationActor.tell("my message", someSenderActor);
The simpliest way is to sending messages with the ref to the source Client_Actor
Client
sendMsg(Client to, Client resultTo)
Client_Actor
req_data(Client to){
sendMsg(to, this);
}
This is good option, if you dont know, which Client has the result for the original poster and which is not.
If you know this and the Client_Actor is only one (like we have a tree and these and only LEAFS will always response to and only Client_Actor), you can do something like this :
Client
register_actor(Client actor){this.actor = actor;}
call_actor(){ this.actor.sendMsg(); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With