I have an actor which creates a child actor to perform some lengthy computations.
The problem is that the initialization of the child actor takes a few seconds and all
I think what you might be looking for is the combo of Stash
and become
. The idea will be that the child actor will set it's initial state to uninitialized, and while in this state, it will stash all incoming messages until it is fully initialized. When it's fully initialized, you can unstash all of the messages before swapping behavior over to the initialized state. A simple example is as follows:
class ChildActor2 extends Actor with Stash{
import context._
var dep:SlowDependency = _
override def preStart = {
val me = context.self
Future{
dep = new SlowDependency
me ! "done"
}
}
def uninitialized:Receive = {
case "done" =>
unstashAll
become(initialized)
case other => stash()
}
def initialized:Receive = {
case "a" => println("received the 'a' message")
case "b" => println("received the 'b' message")
}
def receive = uninitialized
}
Notice in the preStart
that I'm doing my initialization asynchronously, so as to not halt the startup of the actor. Now this is a bit ugly, with closing over the mutable dep
var. You could certainly handle it by instead sending a message to another actor that handles instantiation of the slow dependency and sends it back to this actor. Upon receiving the dependency, it will then call become
for the initialized
state.
Now there is one caveat with Stash
and I'll paste it in right from the Akka docs:
Please note that the Stash can only be used together with actors that
have a deque-based mailbox. For this, configure the mailbox-type of the
dispatcher to be a deque-based mailbox, such as
akka.dispatch.UnboundedDequeBasedMailbox (see Dispatchers (Scala)).
Now if this does not suite you, you can try a more DI
type approach and let the slow dependency be injected into the child actor via it's constructor. So you would define the child actor like so:
class ChildActor(dep:SlowDependency) extends Actor{
...
}
Then when starting up this actor, you would do it as follows:
context.actorOf(new Props().withCreator(new ChildActor(slowDep)), name = "child-actor")