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.
Akka actors are asynchronous from the beginning. Reactive programs can be implemented in either way, synchronous and asynchronous.
Start Hook This method is called when the actor is first created.
Behind the scenes Akka will run sets of actors on sets of real threads, where typically many actors share one thread, and subsequent invocations of one actor may end up being processed on different threads.
In Akka you can't create an instance of an Actor using the new keyword. Instead, you create Actor instances using a factory spawn methods. Spawn does not return an actor instance, but a reference, akka. actor.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With