Akka.NET - 停止顽固的参与者恢复



我有一个带有持久角色A的 actor 系统。在收到消息M时,这应该生成一个持久参与者B的实例,该实例执行一些危险且长时间运行的进程(涉及与其他方交换其他消息),并将消息N发回给A。收到N后,A应终止B

Spawining 是这样实现的:当A收到M 时,它会验证、计算并创建一个持久化的事件M'。应用事件时,A会使用预先计算的信息生成子项。如果此时重新启动系统,M'将重播到A,它将创建同一子B的新化身。

我正在努力解决的是恢复系统时处理终止儿童的情况:我不希望在重新启动系统之前看到任何终止的B

最初我只是从家长那里发送毒丸消息,但由于顽固的演员不会存储任何关于接收这种命令的事件,只是善意地死去,所以当系统恢复时,他们故事的最后一章不会重播给他们,他们只是继续闲逛。

我采用了不同的方法,并尝试在处理A的恢复消息时调用Context.Stop(child),但这会导致所有这些B在恢复之前被终止,从而导致系统记录问题,例如恢复超时。

所以我想我要么在被杀死之前让B恢复,要么一开始就不重新创建它。

我现在要做的是在对象中引入一个代表 B 状态的标志,创建一个要发送的自定义消息而不是 PoisonPill,以便B可以保留被终止的事件,并在它收到恢复完成的信息时,检查此字段并自行终止。但是对于重启时不复活死去的演员的简单要求来说,这看起来工作量很大,所以我想知道我是否做错了什么或试图重新发明热水。

虽然从Persist(domainEvent, callback)调用的持久回调只会被调用一次,但在参与者的生命周期中,恢复过程的实际处理程序可能会(并且可能会)为同一事件调用多次。因此,保持其行为幂等非常重要 - 在恢复处理程序调用上创建新子级时,情况并非如此。

对于像您这样的情况,最好的主意似乎是在恢复期间创建有关挂起的子进程的注释,但是它们的创建应推迟到恢复过程完成 - 这可以通过覆盖持久参与者的OnReplaySuccess方法来执行。此时,您应该能够确定哪些儿童演员应该活着,哪些孩子过去已经完成了处理,因此只复活必要的孩子应该很容易。

最新更新