当父母演员停止时,不要立即停止儿童Akka演员

时间:2017-08-08 17:00:30

标签: scala akka actor

我有一个演员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。这是一个新的应用程序,因此欢迎设计替代方案。

1 个答案:

答案 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 ... } } 对演员的结果。