barbara
barbara

Reputation: 3201

What is the best way to get an actor from the context in Akka?

I tried two ways:

But I have that feeling I'm doing something wrong.

Code of my actor:

def receive: Receive = {
  case "msg" ⇒ {

    ...

    val reader = Await.result(context.actorSelection("akka://Post/user/John").resolveOne(3 seconds), 10 seconds)
    reader ! data
  }
}

Upvotes: 0

Views: 433

Answers (1)

Arne Claassen
Arne Claassen

Reputation: 14414

You should never block inside an Actor's receive loop. At best it wastes resources, at worse it could lead to a deadlock where the resolution cannot happen because all threads in the thread pool are already in use.

Your best options are:

Send the message directly to the actorSelection

You can just call tell directly on the actor selection. Of course, you don't know if the resolution succeeds. And if this happens a lot, it's certainly less efficient than having the actorRef hang around.

context.actorSelection("akka://Post/user/John").resolveOne(3 seconds) ! data

Resolve the selection asynchronously

Given that you have a Future on your hand you could either send your message in the onComplete or use pipeTo to send the resolved ref back to the yourself:

send on resolution

def receive = {
  case data:Data =>
    context.actorSelection("akka://Post/user/John").resolveOne(3 seconds)
      .onComplete {
         case Success(reader) => reader ! data
         case Failure(e) => // handle failure
      }
}

pipe to self

case class Deferred(data: Data, ref: ActorRef)

var johnRef: Option[ActorRef] = None

def receive = {
  case data:Data => johnRef match {
    case Some(reader) => reader ! data
    case None => context.actorSelection("akka://Post/user/John")
      .resolveOne(3 seconds)
      .map( reader => Deferred(data,reader)
      .pipeTo(self)

  case Deferred(data,ref) =>
    johnRef = Some(ref)
    ref ! data
}

Upvotes: 2

Related Questions