Create Akka actor in another actor - scala

I create an actor A. When I send a message to A, the receive method tries to create an actor B. When I run a piece of code that calls:
context.system.actorOf(Props[B], "B")
I get an exception:
InvalidActorNameException: actor name [B] is not unique!
Do you have any idea why this is happening?

Actor paths (part of which is the name that you pass to system.actorOf or context.actorOf, if you use the variants of actorOf that take a name) must be unique in an actor system. You're probably sending more than one message to actor A: every time actor A receives this message, it tries to create a top-level actor B with the name "B". Either drop the name altogether...
context.system.actorOf(Props[B])
...or add a unique identifier to the name. For example:
val uuid = java.util.UUID.randomUUID.toString
context.system.actorOf(Props[B], s"B-${uuid}")
As a side note, top-level actors (i.e., actors created via system.actorOf) should be made sparingly, as the documentation advises:
Top-level actors are the innermost part of your Error Kernel, so create them sparingly and prefer truly hierarchical systems. This has benefits with respect to fault-handling (both considering the granularity of configuration and the performance) and it also reduces the strain on the guardian actor, which is a single point of contention if over-used.
If your intent is to create an actor B as a child of actor A every time the latter receives a message, then use context.actorOf.

Related

Can an Akka Actor Handle Multiple Message Types in Akka Typed

Is it possible to handle multiple message types from a single actor.
For example, assume there is an actor called TradingStrategy that trades stocks. It takes in pricing data pumped in from another Actor. When it decides to place a trade, it sends a message to an another Actor, call it OrderActor, to place a trade. But the TradingStrategy Actor is interested in knowing whether or not the order placed was successful or rejected, etc... because it may change its strategy based on the results from the place order action. In this example, it seems the TradingStrategy needs to handle messages for pricing updates AND order updates. Is this possible with Akka typed? Are there ways to handle this situation?
Here is a code example:
IEXData is the data message.
def apply(orderActor: ActorRef[OrderCommand]): Behavior[IEXData] = Behaviors.setup { context =>
new SimpleTradingStrategy(context, brokerActor)
}
}
class SimpleTradingStrategy(
context: ActorContext[IEXData],
orderActor: ActorRef[OrderCommand],
ticker: Ticker = "spy"
) extends AbstractBehavior[IEXData](context) {
TradingStrategy's protocol would have to include messages indicating order updates. A TradingStrategy actor can register a message adapter which will translate the messages sent by the order actor into TradingStrategy's protocol: the TradingStrategy can present the "virtual" ActorRef returned by the message adapter to the order actor without the order actor knowing that its a TradingStrategy.

Akka actorSelection vs actorOf Difference

Is there a difference between these two? When I do:
context.actorSelection(actorNameString)
I get an ActorSelection reference which I can resolve using the resolveOne and I get back a Future[ActorRef]. But with an actorOf, I get an ActorRef immediately. Is there any other vital differences other than this?
What might be the use cases where in I would like to have the ActorRef wrapped in a Future?
actorOf is used to create new actors by supplying their Props objects.
actorSelection is a "pointer" to a path in actor tree. By using resolveOne you will get actorRef of already existing actor under that path - but that actorRef takes time to resolve, hence the Future.
Here's more detailed explanation:
http://doc.akka.io/docs/akka/snapshot/general/addressing.html
An actor reference designates a single actor and the life-cycle of the reference matches that actor’s life-cycle; an actor path represents a name which may or may not be inhabited by an actor and the path itself does not have a life-cycle, it never becomes invalid. You can create an actor path without creating an actor, but you cannot create an actor reference without creating corresponding actor.
In either processes, there is an associated cost of producing an ActorRef.
Creating user top level actors with system.actorOf cost a lot as it has to deal with error kernel initialization which also cost significantly. Creating ActorRef from child actor is very fair making it suitable for one actor per task design. If in an application, for every request, a new set of actors are created without cleanup, your app may run out of memory although akka actors are cheap. Another good is actorOf is immediate as you mentioned.
In abstract terms, actorSelection with resolveOne looks up the actor tree and produces an actorRef in a future as is not so immediate especially on remote systems. But it enforces re-usability. Futures abstract the waiting time of resolving an ActorRef.
Here is a brief summary of ActorOf vs. ActorSelection; I hope it helps:
https://getakka.net/articles/concepts/addressing.html
Actor references may be looked up using the ActorSystem.ActorSelection
method. The selection can be used for communicating with said actor
and the actor corresponding to the selection is looked up when
delivering each message.
In addition to ActorSystem.actorSelection there is also
ActorContext.ActorSelection, which is available inside any actor as
Context.ActorSelection. This yields an actor selection much like its
twin on ActorSystem, but instead of looking up the path starting from
the root of the actor tree it starts out on the current actor.
Summary: ActorOf vs. ActorSelection
ActorOf only ever creates a new actor, and it creates it as a direct
child of the context on which this method is invoked (which may be any
actor or actor system). ActorSelection only ever looks up existing
actors when messages are delivered, i.e. does not create actors, or
verify existence of actors when the selection is created.

Should Akka messages be unique for a sender-receiver pair?

Best practices question:
Should an Akka message type (case class) be always only sent by a single type of actor and received only by a single type of actor?
Example:
Three actor types: MainSender, MainReceiver, Worker
MainSender sends a message DoSomething(work) to MainReceiver.
MainReceiver forwards the DoSomething(work) message to Worker.
Is this the best practice? Or would it be better to define a new case class for the other sender-receiver pair?
MainSender sends a message DoSomething(work) to MainReceiver.
MainReceiver sends a message StartWorking(work) to Worker.
You can totally send the same message to any actor as long as it makes sense in your architecture. It is totally encouraged to reuse your code.
As you suggested, that is exactly what the forward function does.
The same logic goes for Exception: if you want to throw an Exception, you can use an existing one if it fits your needs or create a new one otherwise.

How generate unique id for Actor?

Suppose I have an application that uses actors for processing User. So there is one UserActor per user. Also every user Actor is mapped to user via id, e.g. to process actions with concrete user you should get Actor like that:
ActorSelection actor = actorSystem.actorSelection("/user/1");
where 1 is user id.
So the problem is - how generate unique id inside cluster effectively? First it needs to check that new id will not duplicate an existent one. I can create one actor for generating id's which will live in one node, and before creating any new UserActor Generator is asked for id, but this leads to additional request inside cluster whenever user is created. Is there a way to do this more effective? Are there build-in akka techniques to do that?
P.S. May this architecture for using Actor is not effective any suggestion/best practice is welcome.
I won't say whether or not your approach is a good idea. That's going to be up to you to decide. If I do understand your problem correctly though, then I can suggest a high level approach to making it work for you. If I understand correctly, you have a cluster, and for any given userId, there should be an actor in the system that handles requests for it, and it should only be on one node and consistently reachable based on the user id of the user. If that's correct, then consider the following approach.
Let's start first with a simple actor, let's call it UserRequestForwarder. This actors job is to find an actor instance for a request for a particular user id and forward on to it. If that actor instance does not yet exist, then this actor will create it before forwarding onto it. A very rough sketch could look like this:
class UserRequestForwarder extends Actor{
def receive = {
case req # DoSomethingForUser(userId) =>
val childName = s"user-request-handler-$userId"
val child = context.child(childName).getOrElse(context.actorOf(Props[UserRequestHandler]))
child forward req
}
}
Now this actor would be deployed onto every node in the cluster via a ConsistentHashingPool router configured in such a way that there would be one instance per node. You just need to make sure that there is something in every request that needs to travel through this router that allows it to be consistently hashed to the node that handles requests for that user (hopefully using the user id)
So if you pass all requests through this router, they will always land on the node that is responsible for that user, ending up in the UserRequestForwarder which will then find the correct user actor on that node and pass the request on to it.
I have not tried this approach myself, but it might work for what you are trying to do provided I understood your problem correctly.
Not an akka expert, so I can't offer code, but shouldn't the following approach work:
Have a single actor being responsible for creating the actors. And have it keep a Hashset of actor names, for actors that it created, and that didn't die already.
If you have to spread the load between multiple actors you can dispatch the task based on the first n digits of the hashcode of the actor name that has to be created.
It seems like you have your answer on how to generate the unique ID. In terms of your larger question, this is what Akka cluster sharding is designed to solve. It will handle distributing shards among your cluster, finding or starting your actors within the cluster and even rebalancing.
http://doc.akka.io/docs/akka/2.3.5/contrib/cluster-sharding.html
There's also an activator with a really nice example.
http://typesafe.com/activator/template/akka-cluster-sharding-scala

Doesn't this create new ActorSystem everytime?

Confirming that every time you call Akka.system.actorOf or Akka.system.scheduler it'll create a new ActorSystem in the application? Looking at some code where it calls Akka.system.actorOf every time it has to create a new actor, which I think should have been context.actorOf to use the existing ActorSystem (which should have been created at the app startup). Is my understanding correct that calling Akka.system.actorOf every single time, to create a new actor, is very wrong?
You create new ActorSystem only when you call ActorSystem.apply method:
val system = ActorSystem("YourApplication")
Of course, when you call methods on the system you do not create new systems, that is, the following:
val actor = system.actorOf(Props[SomeActor], "someActor")
won't create new system, it will just create new top-level actor in the system. You usually call system.actorOf method when you are outside of an actor, for example, in initialization code when there are no actors created yet.
context, on the other hand, is a way to interact with the system from inside an actor. context is a member of Actor trait, which is inherited into your actors. You use context to access actor system's scheduler, to watch actors, to create child actors, to change actor's behavior etc. context.actorOf will create child actor.
So no, calling system.actorOf for creating actors is absolutely not wrong. You just have to keep in mind that when you use system.actorOf you're creating top-level actors, and that's not something you need always. Usually you create one or several top-level actors, which then in turn create child actors and so on.
According to the docs:
Using the ActorSystem will create top-level actors, supervised by the
actor system’s provided guardian actor, while using an actor’s context
will create a child actor.
So basically, it depends on what you want to achieve.
More details here.
EDIT:
Concerning your concrete question (I am sorry, I misunderstood you), you should see an ActorSystem as a heavyweight structure that will allocate up to N threads, and each Actor will run within one of these threads (the key point here is that there is no mutable state). ActorSystems share common configuration, e.g. dispatchers, deployments, remote capabilities and addresses. They are also the entry point for creating or looking up actors.
Creating an ActorSystem is very expensive, so you want to avoid creating a new one each time you need it. Also your actors should run in the same ActorSystem, unless there is a good reason for them not to. The name of the ActorSystem is also part the the path to the actors that run in it.
There is no Akka.system.actorOf method in the current API. Normally you hold a reference to the application ActorSystem as others already showed you, and create child actors from that context:
val system = akka.actor.ActorSystem("YourApplication");
val actor1 = system.actorOf(Props[Actor1], "Actor1")
val actor2 = system.actorOf(Props[Actor2], "Actor2")
So, in short, I have never tried it but I assume every call to akka.actor.ActorSystem will try to create a new ActorSystem and it would probably fail if no different ActorSystem names/configurations are provided.
You can only have one ActorSystem in a Cluster. thats why you cant use new.
Something very similar to main..
trying to learn by answering to it.