I think the extension idea is a good one as long as your registry actor is always going to be in the same ActorSystem
.
Alternatively, using actorSelection
(adapted from Remote Lookup):
class RegistryClient extends Actor {
val path = "/path/to/registry/actor"
context.setReceiveTimeout(3.seconds)
def sendIdentifyRequest(): Unit =
context.actorSelection(path) ! Identify(path)
def receive = {
case ActorIdentity(`path`, Some(ref)) ⇒
context.setReceiveTimeout(Duration.Undefined)
context.become(active(ref))
case ActorIdentity(`path`, None) ⇒
throw new RuntimeException("Registry not found")
case ReceiveTimeout ⇒ sendIdentifyRequest()
}
def active(registry: ActorRef): Actor.Receive = {
// use the registry
}
}
This will work for remote or local actors.
Let's look at the extension solution. Actors are created asynchronously. Therefore your extension constructor won't fail when calling actorOf
if the actor fails to initialize.
If you want to know for sure that the actor failed to initialize then one way to know is to ask
the actor something that it will respond to and Await
a response. The Await
will throw a TimeoutException
if the actor fails to respond.
class RegistryExtension(system: ExtendedActorSystem) extends Extension {
val registry = system.actorOf(Props[Registry], "registry")
implicit val timeout: Timeout = Timeout(500.millis)
val f = registry ? "ping" // Registry should case "ping" => "pong"
Await.result(f, 500.millis) // Will throw a TimeoutException if registry fails
// to respond
}
The TimeoutException
will get thrown when you call RegistryExtension(system).registry
the first time.