我有主管演员根据收到的命令选择儿童演员,每当它创建一个新的儿童演员并且发送消息(询问模式)它超时作为儿童演员试图发回反应但是它去死信。
这是儿童演员代码
class IdActor(id: String, injector: Injector) extends Actor {
override def receive: Receive = {
case cmd: GenerateIdCmd =>
val parent = sender()
...
Future(idEvent) pipeTo sender //Issue is here going to dead letters
//Future(idEvent) pipeTo parent //This also leads to same problem
//parent ! idEvent // Same issue
}
}
这是主管代码
class IdSupervisor(injector: Injector) extends Actor {
override def receive: Receive = {
case cmd: GenerateIdCmd =>
...
val ref = context.child(cmd.id).getOrElse {
context.actorOf(Props(classOf[IdActor], cmd.id, injector), cmd.id)
}
ask(ref, cmd) pipeTo sender
}
}
第二条消息正在流回始发者,所有新的儿童演员的第一个回应是从那里开始致死的信件。
工作解决方案 问题在于Supervisor,固定代码
class IdSupervisor(injector: Injector) extends Actor {
override def receive: Receive = {
case cmd: GenerateIdCmd =>
val originator = sender
...
val ref = context.child(cmd.id).getOrElse {
context.actorOf(Props(classOf[IdActor], cmd.id, injector), cmd.id)
}
ask(ref, cmd) pipeTo originator
}
}
答案 0 :(得分:1)
永远不会从未来的演员内部直接发送给发件人,sender
是def
,并且在未来完成时,它可能已经不同于您的预期。解决方案之一是在将来调用之前存储发件人:
class IdActor(id: String, injector: Injector) extends Actor {
override def receive: Receive = {
case cmd: GenerateIdCmd =>
...
val originalSender = sender
Future(idEvent) pipeTo originalSender
}
}
答案 1 :(得分:1)
我怀疑当孩子按照你的描述答复父母时,实际上并没有发生这个问题,但是当父母向孩子发送信息并希望得到回复时:
val ref = context.child(cmd.id).getOrElse {
context.actorOf(Props(classOf[IdActor], cmd.id, injector), cmd.id)
}
ask(ref, cmd) pipeTo sender
actor在创建时异步启动。观察到,当创建一个新子节点时,该子节点的第一条消息会导致死信,而后续消息传递给该子节点会产生预期行为,这表明了一个actor初始化问题。可能发生的事情是,儿童演员在完全开始之前收到他们的第一条GenerateIdCmd
消息。