Reputation: 14404
I'm trying to find the proper pattern for initializing an actor asynchronously, so that I can look up dependent ActorRef
s it needs. I want to avoid using ActorSelection
, since it's
tell
sLooking at the Actor LifeCycle it seems to be all pretty much synchronous until the message loop starts, including preStart
, etc., which leads me to think that I have only one of two choices:
Use a factory method with a signature of Future[ActorRef]
All dependencies for constructing the actor are resolved asynchronously and passed in via Props
.
The main problem with this approach is that you cannot use this factory to construct an actor inside of another actor, since it then has the same problem, i.e. it's turtles all the way down, wiring up the hierarchy of all actors and their dependencies asynchronously.
Use become
and stash
to transition the actor
The actor is created with actorOf
, immediately resulting in an ActorRef
but it starts in an Initialization state, does it's dependency resolution, stash
ing incoming messages in the meantime, and finally become
ing the Running state and unstashAll
ing.
This feels a lot more idiomatic for actors, even though my dependencies will all be var
instead of val
.
Both seem like a lot of overhead, making me wondering if I these are the best options or if I just haven't found the proper pattern in the docs.
Upvotes: 10
Views: 809
Reputation: 7247
There's no reason your dependencies have to be vars
when using become:
val initializing: Actor.Receive = {
case Dependencies(d1, d2) => context.become(working(d1, d2))
}
def working(d1: Dependency, d2: Dependency): Actor.Receive = {
case msg => d1.fetch(...) // whatever
}
def receive = initializing
Also, actorFor
is a) deprecated and b) doesn't create an actor.
Upvotes: 8