Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Actor selection

Tags:

scala

akka

Why when I select an absolute path with ActorContext it doesn't works (the actor isn't correctly selected and doesn't receive the HelloResponse message) ?

//From Actor2:
//This doesn't work (Message never received)
context.actorSelection("/user/actor1") ! HelloResponse("hello back1")
//This works (actor 1 receives the message)
context.system.actorSelection("/user/actor1") ! HelloResponse("hello back2")

I'm newbie to Scala/Akka but reading documentation it seems that should work.

like image 230
lujop Avatar asked Apr 28 '13 09:04

lujop


3 Answers

This is a bug, thanks for asking: https://www.assembla.com/spaces/ddEDvgVAKr3QrUeJe5aVNr/tickets/3276

like image 134
Roland Kuhn Avatar answered Sep 25 '22 00:09

Roland Kuhn


When you use context.actorSelection inside of an actor, what you are saying is find an actor under this current actors control (started by/supervised by). Since actor1 was probably not started by actor2 (or is not supervised by actor2), then it won't resolve to anything. If actor1 was actually owned/started by actor2 then you could probably do context.actorSelection("/actor1") to get that child actor of actor2. The reason context.system.actorSelection works is because you are going all the way "up" to system first before starting your search and fully qualifying the path to the actor. System "owns" actor1 if you started it up as system.actorOf, so using that path will allow you to get to it starting from system.

A little code to show what I mean:

class Actor1 extends Actor{
  override def preStart = {
    context.actorOf(Props[Actor2], "actor2")
  }
  def receive = {
    case _ =>
  }
}

class Actor2 extends Actor{
  override def preStart = {println("my path is: " + context.self.path)}
  def receive = {
    case _ =>
  }
}

object FutureTesting {
  def main(args: Array[String]) {
    val sys = ActorSystem("test")
    implicit val ec = sys.dispatcher

    //Starting an Actor2 from system
    sys.actorOf(Props[Actor2], "actor2")

    //Starting an Actor1 from system which in turn starts an Actor2
    sys.actorOf(Props[Actor1], "actor1")
  }
}

When you run this example, you will see:

my path is: akka://test/user/actor1/actor2
my path is: akka://test/user/actor2

So you can see that I have 2 instances of Actor2 running in my system; one spawned directly from sys tied to /user/actor2 as it's lookup path and one started from an instance of Actor1 tied to /user/actor1/actor2 for its path.

The actor system is hierarchical and this example shows that. The ActorSystem itself is the root to everything. Selecting actors is then similar to XPath in that the context that you are issuing the select from matters.

like image 39
cmbaxter Avatar answered Sep 24 '22 00:09

cmbaxter


From actor2 you will need to use

context.actorSelection("/actor1")

I agree it is not intuitive given the metaphor is a filesystem and when using a filesystem a leading / is an absolute path meaning start at the root. Also it is inconsistent with actorFor because

context.actorFor("/user/actor1")

returns the top level Actor1 (see Absolute and Relative Paths)

EDIT - this was a bug that was fixed in Akka 2.1.4 (see Roland's answer). From 2.1.4 onwards you can use context.actorSelection("/user/actor1").

like image 34
sourcedelica Avatar answered Sep 25 '22 00:09

sourcedelica