Get reference to supervised nested actor - scala

I have a setup in which an actor(A) creates an actor(B) which it supervises and restarts when it crashes. From outside the actor system I want to get some value from the 'nested' actor B.
I can directly ask the actorSystem for the nested actor using:
val nestedActorB = myActorSystem.actorFor("/user/A/B")
Can I keep a reference to this actor or should I ask the actorSystem for the ref each time I want to ask the nested actor something. (Or should I ask the parent actor for the ref)?
What would be a best practice in this scenario?
(scala 2.9.1 and akka 2.0.4)
Thanks,
Albert

Yes you can keep a reference to the actor and not ask the system every time with actorFor.
There is a difference between local and remote actors and the documentation passage you are referring to is ambiguous and I've opened a ticket.
A local actor is only looked up once during the actorFor call so it needs to exist before you look it up, while sends to a remote actor are always by path and the remote actor is looked up on the remote node every time.

Even after the restart the reference stays the same. B will always be a child of A so the "/A/B" path is stable. If A is a top level actor, you will always find him under"/user/A". So yeah, "/user/A/B" will always point to the same actor.

As you can see in the akka doc, a reference is an object that, at runtime, traverses the actor tree every time you send a message or check the liveliness of the actor you are referring to.
This means you can use the reference you obtain with the actorFor method any time you want to communicate with that actor, even if the actor belonging to that path is restarted or even if it's already terminated.

Related

Akka acessing actor from another tree branch

I have Akka application with several actors. Actor tree looks something like this:
/user
/one TARGET
/two /three
SOURCE
In the source actor I have to send message to TARGET actor. However, I don't know how to do it properly.
Resolving ActorRef from ActorSelection every time seems to be very bad.
Are there any patterns?
The two patterns I am aware of and use are:
Pass the ActorRef of TARGET in the original message sent to SOURCE, so that way SOURCE knows to respond to TARGET. This works well when TARGET is different from message to message, and makes unit testing easy.
Resolve the TARGET ActorRef from the ActorSelection once in either an ESB or Service Locator, and pass that through to SOURCE, and use that. This works well when there is exactly one instance of TARGET in the actor system, however it will make unit testing a little more complex.

How to intercept logs from a different ActorSystem in scala.testkit.eventfilter?

I have a Scala class ComponentBuilder which deals with creating actors and initializing them. It has a field system corresponding to the ActorSystem (among other things).
Now, I'd like to test it using TestKit - intercept logs which actors produce and check them. If I try to use regular EventFilter I can see the log which my actors produce in stdout, but the EventFilter doesn't catch them, I guess because they are in a different ActorSystem.
One solution I thought of was to make ComponentBuilder a subclass of ActorSystem and pass all the AS-commands to its field. I didn't manage to do it, due to protected methods that return InternalActorRef, but anyway I'm not sure if it'll work then, as there will be 2 actor systems anyway.
I also tried to pass some messages from testing class to the actor and wait and check the results. This results in replying to the deadLetters, probably for the same reason - the inner ActorSystem doesn't know about the outer one.
I will appreciate any solution you may have.

How to acquire actor reference to typed actor implementation in Akka?

For Akka 2.2 how do I get a reference to a TypedActor. For untyped Actors we are advised to use ActorSelection and then use tell on ActorSelection. What should I do for TypedActor?
I don't use typed actors, but I'm going to take a shot at answering this question anyway based on the documentation and a little guess work. I don't believe Typed Actors and ActorSelections work directly together. If you think about an ActorSelection, it's really a proxy to 0 to many actual ActorRefs that match whatever query was used in the actorSelection call that yielded it. This selection works well with untyped actors in cases where you want to broadcast the same message to a set of actors. Sitting a typed proxy in front of this seems to make less sense as I can't think of a ton of use cases where you want narrowed typing and to broadcast to a set of possible destinations and potentially receive responses (i.e. ask).
Now, if you have an ActorSelection, and you want to query that selection for a single ref under it (by using either Identify or resolveOne) and you get back an ActorRef, then you can snap a typed actor proxy in front of it like so:
val typedActor =
TypedActor(system).typedActorOf(TypedProps[MyTypedActor],myLookedUpRef)
This technique basically takes a looked up untyped actor and narrows it into a TypedActor that you can now communicate with via the TypedActors interface.
You can read more about TypedActors here and more about resolving ActorSelections here.

What is the best way to get a reference to an Akka Actor

I am a little confused by how I am supposed to get a reference to my Actor once it has been crerated in the Akka system. Say I have the following:
class MyActor(val x: Int) extends Actor {
def receive = {
case Msg => doSth()
}
}
And at some stage I would create the actor as follows:
val actorRef = system.actorOf(Props(new MyActor(2), name = "Some actor")
But when I need to refer to the MyActor object I cannot see any way to get it from the actor ref?
Thanks
Des
I'm adding my comment as an answer since it seems to be viewed as something worth putting in as an answer.
Not being able to directly access the actor is the whole idea behind actor systems. You are not supposed to be able to get at the underlying actor class instance. The actor ref is a lightweight proxy to your actor class instance. Allowing people to directly access the actor instance could lead down the path of mutable data issues/concurrent state update issues and that's a bad path to go down. By forcing you to go through the ref (and thus the mailbox), state and data will always be safe as only one message is processed at a time.
I think cmbaxter has a good answer, but I want to make it just a bit more clear. The ActorRef is your friend for the following reasons:
You cannot ever access the underlying actor. Actors receive their thread of execution from the Dispatcher given to them when they are created. They operate on one mailbox message at a time, so you never have to worry about concurrency inside of the actor unless YOU introduce it (by handling a message asynchronously with a Future or another Actor instance via delegation, for example). If someone had access to the underlying class behind the ActorRef, they could easily call into the actor via a method using another thread, thus negating the point of using the Actor to avoid concurrency in the first place.
ActorRefs provide Location Transparency. By this, I mean that the Actor instance could exist locally on the same JVM and machine as the actor from which you would like to send it a message, or it could exist on a different JVM, on a different box, in a different data center. You don't know, you don't care, and your code is not littered with the details of HOW the message will be sent to that actor, thus making it more declarative (focused on the what you want to do business-wise, not how it will be done). When you start using Remoting or Clusters, this will prove very valuable.
ActorRefs mask the instance of the actor behind it when failure occurs, as well. With the old Scala Actors, you had no such proxy and when an actor "died" (threw an Exception) that resulted in a new instance of the Actor type being created in its place. You then had to propagate that new instance reference to anyone who needed it. With ActorRef, you don't care that the Actor has been reincarnated - it's all transparent.
There is one way to get access to the underlying actor when you want to do testing, using TestActorRef.underlyingActor. This way, you can write unit tests against functionality written in methods inside the actor. Useful for checking basic business logic without worrying about Akka dynamics.
Hope that helps.

Actor addresses and tests

I'm building up an actor hierarchy in which some actors reply to messages they get directly to a well-known actor (fixed name). I.e. these actors (far-removed in the hierarchy) obtain an actorRef via context.actorFor("akka://...").
I.e. for example, I have an "orchestrating" actor:
system.actorOf(Props[OrchestratingActor], name = "orchestrator")
which will then have an address of the kind akka://application/user/orchestrator
and someplace else, a random worker that received a message and wants to talk to the orchestrator:
class RandomWorker extends Actor {
def theOrchestrator = context.actorFor("akka://application/user/orchestrator")
def receive = {
case Foo =>
theOrchestrator ! "Bar"
}
}
Now, I'd like to test those actors and am wondering about how to deal with those addresses: when unit-testing an actor (e.g. using TestActorRef), how do I go about checking what's being sent to the remote address? One idea would be to (when possible) provide the address to the well-known actor via the constructor, and pass in the address of a TestActor to see what's being received. However I wonder if there isn't a way to "impersonate" a given address in the test, esp. in situation where the addresses aren't simple.
In other words I'd like to test the behavior of the actor (will it indeed have sent "Bar" to the orchestrator upon receiving a Foo
My recommendation would be to avoid using look-ups of actors for the purpose you show. It is rather a tool for the setup phase of your application, when wiring it all together. But even then most actors’ supervisors will know the dependencies of their children without using look-ups.
Within a local actor system all ActorRefs can be injected top to bottom (using constructor arguments or introduction messages). Look-ups are most useful when introducing remote systems with each other.
There is nothing wrong with injecting the address via the constructor. Let it me know if you need any details, because at the moment I don't know how to make this more clear, since you basically answered your own question. And btw, I don't know, which Akka version you are using, but actorFor has been recently deprecated in favor of ActorSelection, and there are good reasons for this.