別のアクターを監視するアクターがあります (これはリモートであるため、直接参照することはできません)。actorSelection
andを使用してアクターへの参照を取得しIdentify
、結果の を監視しActorRef
ます。それはうまくいきます。
しかし、他のアクターが終了したときと同じように自動的に再接続したいので、同じものを再利用しactorSelection
ます (アクターは同じ場所でインスタンス化されます) が、今回はルックアップ経由でIdentify
永遠に失敗します。アクターが最初にすでにインスタンス化されているがそうでない場合、なぜそれが機能するのか、私には手がかりがありません。
編集: リモートjvmが完全に終了しているにもかかわらず、最初の接続の前に関連付けエラーが発生するのに対し、再接続しようとするとエラーが発生しないことも奇妙です。失敗してから約 1 分以上待つと、関連付けエラーが返され、接続が再び成功することに気付きました。これを構成する方法はありますか (キャッシュですか?) メカニズム。
それは標準的な動作ですか、それとも何か問題がありましたか?
コードで何かを台無しにした場合:
object ServerMonitor {
case object Request
case class Reply(ref: ActorRef)
}
class ServerMonitor(path: String) extends Actor with ActorLogging {
import ServerMonitor._
var server: Option[ActorRef] = None
var listeners: Set[ActorRef] = Set.empty
def receive = {
case ActorIdentity("server", Some(ref)) =>
server = Some(ref)
context.watch(ref)
listeners.foreach(_ ! Reply(ref))
listeners = Set.empty
log.info(s"connected to the server at $path")
case ActorIdentity("server", None) =>
server = None
log.warning(s"couldnt reach the server at $path")
import context.dispatcher
context.system.scheduler.scheduleOnce(1 second) {
context.actorSelection(path) ! Identify("server")
}
case Terminated(ref) =>
log.warning("server terminated")
server = None
context.actorSelection(path) ! Identify("server")
case Request =>
server.fold {
listeners += sender
} { ref =>
sender ! Reply(ref)
}
}
override def preStart() {
context.actorSelection(path) ! Identify("server")
}
}