Akka.NET - 在恢复时阻止持久的演员

时间:2018-02-15 15:23:36

标签: akka.net akka.net-persistence

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

Spawining以这种方式实现:当 A 收到 M 时,它会验证,计算并创建一个持久存储的事件 M'。应用事件后, A 会生成包含预先计算信息的子项。如果系统此时重新启动, M'将重播为 A ,它将为同一个孩子 B 创建一个新版本

我正在努力解决的问题是在恢复系统时处理被终止的孩子的情况:我想看到在重新启动系统之前终止的任何 B

最初我只是从父母那里发送毒丸消息,但由于持久性演员没有存储关于接收这样一个命令的任何事件,并且只是善待,当系统正在恢复时,他们故事的最后一章不是重播给他们,他们只是一直闲逛。

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

所以我想我必须让 B 在被杀之前恢复,或者不首先重新创建它。

我现在要做的是在对象中引入一个表示 B 状态的标志,创建一个要发送的自定义消息而不是PoisonPill,以便 B 可以持续终止事件,并且当它收到完成恢复的信息时,检查此字段并终止自身。但是看起来很多工作都是为了在重新启动时没有复活死亡演员的简单要求,所以我想知道我是在做一些完全错误的事情还是试图重新发明热水。

1 个答案:

答案 0 :(得分:1)

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

对于像你这样的案例,最好的想法似乎是在恢复期间创建一个关于待处理子进程的注释,但是应该推迟创建它们直到恢复过程完成 - 这可以通过覆盖OnReplaySuccess来执行持久性演员的方法。此时,您应该能够确定哪些儿童演员应该保持活着,以及哪些儿童演员过去已经完成了处理,因此只复制必要的演员应该很容易。