我有一个演员p: ParentActor
我希望在使用postStop
方法停止时执行一些清理作业。其中一项工作涉及向儿童演员c: ChildActor
发送消息。之后,应停止c
,然后p
。但是,一旦调用context.stop(p)
,c
似乎会立即停止并且无法接收消息。
以下是我想做的一个例子:
class ParentActor extends Actor {
...
override def postStop {
logger.info("Shutdown message received. Sending message to child...")
val future = c ? "doThing"
logger.info("Waiting for child to complete task...")
Await.result(future, Duration.Inf)
context.stop(c)
logger.info("Child stopped. Stopping self. Bye!")
context.stop(self)
}
}
错误消息中的结果:
[ERROR] [SetSystem-akka.actor.default-dispatcher-5] [akka://SetSystem/user/ParentActor] Recipient[Actor[akka://SetSystem/user/ParentActor/ChildActor#70868360]] had already been terminated. Sender[Actor[akka://SetSystem/user/ParentActor#662624985]] sent the message of type "java.lang.String".
另一种方法是向p
发送一条消息说要关机,并由此发生上述操作,但使用内置的停止功能似乎更好。
PS。这是一个新的应用程序,因此欢迎设计替代方案。
答案 0 :(得分:3)
当演员init(row: Row) throws {
// ...
data = row["data"]?.bytes ?? []
}
func makeRow() throws -> Row {
var row = Row()
// ...
try row.set("data", StructuredData.bytes(data))
return row
}
停止时,其子女确实在A
的{{1}}挂钩调用之前停止。演员停止时的事件顺序如下(来自官方documentation):
一个actor的终止分两步进行:首先,actor暂停其邮箱处理并向其所有子节点发送一个停止命令,然后它继续处理来自其子节点的内部终止通知,直到最后一个消失为止,最后终止自身(调用
A
,转储邮箱,在DeathWatch上发布postStop
,告诉其主管。
覆盖父母postStop
不会帮助您,因为您希望的关机程序包括向孩子发送消息并等待回复。当父母被终止时,孩子在父母Terminated
被运行之前就被停止了。
正如您所提到的,向postStop
发送特定消息以启动关闭是另一种方法。以下内容可行:
postStop
请注意,应避免在actor中使用ParentActor
。相反,pipe import akka.pattern.pipe
class ParentActor extends Actor {
...
def receive = {
case Shutdown =>
(c ? DoYourThing).mapTo[ThingIsDone].pipeTo(self)
case ThingIsDone =>
logger.info("Child has finished its task.")
context.stop(self)
case ...
}
}
对演员的结果。