Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Akka Pattern - Actor tree, reply to original source

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;

  • Create a tree for each connection client and get the actors to keep track of the sender, when they get a 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.
  • Somehow send down the 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)...
  • Somehow lookup the client actor based on a unique id in the messages passed through the tree or use the actorselection (not sure how well this would work with remoting)...
  • Something better...

FYI I'm using Akka 2.2.1.

Cheers!

like image 783
NightWolf Avatar asked Oct 10 '13 16:10

NightWolf


People also ask

How can I send a message to an actor in Akka?

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.

How do I terminate Akka actor?

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.

What is ActorSystem in Akka?

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.

How does Akka handle concurrency?

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.


2 Answers

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);
like image 147
tgood Avatar answered Oct 14 '22 13:10

tgood


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(); }
like image 1
libik Avatar answered Oct 14 '22 12:10

libik