Akka.NET - 在恢复时停止持久性参与者

Akka.NET - stopping persistent actors on recovery

我有一个带有持久化演员的演员系统A。在接收到消息 M 时,这应该会产生一个持久性 actor B 的实例,它会执行一些危险的 long-running 过程(涉及交换其他与其他方的消息),并将消息 N 发送回 A。收到 N 后,A 应该终止 B.

Spawining是这样实现的:当A接收到M时,它会验证、计算并创建一个事件M ',即坚持。应用事件时,A 会生成带有预先计算的信息的 child。如果此时重启系统,M'会重播到A,并且会创建一个相同的[=71]的新化身=] B.

我正在努力的是在恢复系统时处理终止 children 的情况:我想 看到任何 B s 在重新启动系统之前被终止。

最初我只是从 parent 发送毒丸消息,但是由于持久性 actor 不存储任何关于接收此类命令的事件,并且只是善意地死去,当系统正在恢复时,这最后他们故事的章节没有向他们重播,他们只是继续闲逛。

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

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

我现在要做的是在 object 中引入一个标志来表示 B 的状态,创建一个要发送的自定义消息而不是 PoisonPill , 这样 B 可以持久化一个被终止的事件, 当它收到恢复完成的信息时, 检查这个字段并终止自己。但是,为了一个简单的要求,即在重新启动时不让死去的演员复活,这看起来需要做大量的工作,所以我想知道我是在做一些完全错误的事情还是试图重新发明热水。

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

对于像你这样的情况,最好的办法似乎是在恢复期间创建一个关于未决子进程的注释,但是它们的创建应该推迟到恢复过程完成 - 这可以通过覆盖 OnReplaySuccess 持久化演员的方法。在这一点上,你应该能够确定哪些儿童演员应该保持存活,哪些儿童演员已经完成了过去的处理,因此只复活必要的演员应该很容易。