anindyaju99 anindyaju99 - 1 month ago 13
Scala Question

Akka: when is it safe to send a message

I am creating an actor via:

system.actorOf(Props(....))


or

system.actorOf(SmallestMailboxPool(instances).props(Props(....))).


I usually block the thread calling
system.actorOf
till
actorSelection
works.
Await.result(system.actorSelection("/user/" + name).resolveOne(), timeout.duration)


I am wondering if this is at all needed or I can immediately start using the
actorRef
and send (tell) messages to the actor/actor pool.

So the question boils down to, if I have an
actorRef
, does that mean the mailbox is already created or it might so happen that the messages I sent immediately after calling
system.actorOf
might get dropped?

Answer

If you drill down the the implementation of system.actorOf, you see a call to a method names makeChild. Internally, this utilizes a lengthy method on the ActorRefProvider trait (internally using LocalActorRefProvider) called actorOf. This rather lengthy method initializes the child actor. Relevant parts are:

val props2 =
  // mailbox and dispatcher defined in deploy should override props
  (if (lookupDeploy) deployer.lookup(path) else deploy) match {
    case Some(d) ⇒
      (d.dispatcher, d.mailbox) match {
        case (Deploy.NoDispatcherGiven, Deploy.NoMailboxGiven) ⇒ props
        case (dsp, Deploy.NoMailboxGiven)                      ⇒ props.withDispatcher(dsp)
        case (Deploy.NoMailboxGiven, mbx)                      ⇒ props.withMailbox(mbx)
        case (dsp, mbx)                                        ⇒ props.withDispatcher(dsp).withMailbox(mbx)
      }
    case _ ⇒ props // no deployment config found
}

Or if a Router is explicitly provided:

val routerDispatcher = system.dispatchers.lookup(p.routerConfig.routerDispatcher)
val routerMailbox = system.mailboxes.getMailboxType(routerProps, routerDispatcher.configurator.config)

// routers use context.actorOf() to create the routees, which does not allow us to pass
// these through, but obtain them here for early verification
val routeeDispatcher = system.dispatchers.lookup(p.dispatcher)
val routeeMailbox = system.mailboxes.getMailboxType(routeeProps, routeeDispatcher.configurator.config)

new RoutedActorRef(system, routerProps, routerDispatcher, routerMailbox, routeeProps, supervisor, path).initialize(async)

Which means that once you get back an ActorRef, the mailbox has been initialized and you shouldn't be scared of sending it messages.

If you think about the semantics of what an ActorRef stands for, it would be a bit pointless to provide one with an ActorRef which is partly/not initialized. It would make system guarantees weak and would make the programmer think twice before passing messages, which is the opposite desire of the framework.

Comments