在Akka中创建儿童演员类型持久性演员

时间:2018-07-31 16:15:23

标签: scala akka akka-persistence akka-typed

假设使用Akka Typed实现的应用程序具有持久性参与者。此持久性actor作为其操作的一部分,会创建临时(或非持久性)子actor,每个子都有一个唯一的ID,并且这些ID是持久状态的一部分。顽固的参与者也需要与孩子进行交流的方式,但是我们不想保留孩子的ActorRef,因为他们并不是国家的真正组成部分。恢复后,持久性参与者应根据恢复的状态重新创建其子代。听起来这不是一个非常不寻常的用例,我正在尝试找出实现它的最干净方法。我可以在命令处理程序的andThen Effect内创建子角色,这是有副作用的,但是无法从那里保存子ActorRef。这似乎是类型化的Persistence API的一个更一般的特征-很难在持久性参与者中具有非持久性状态(在这种情况下,该状态可用于存储临时子项ActorRef)。我想到的一个解决方案是使用一种“代理”角色来创建子代,保留ID和ActorRef的映射以及基于ID转发消息。持久角色拥有对该代理角色的引用,并在每次需要创建新子角色或向现有子角色之一发送消息时与之联系。我对此有不同的感觉,如果有人可以为我提供更好的解决方案,我将不胜感激。

2 个答案:

答案 0 :(得分:1)

如果您不使用快照,则持久性机制将不存储State对象,而是存储导致该Event对象的State的序列。恢复时,它只是按照发生的顺序重播这些Event,而您的eventHandler将返回一个经过修改的State对象,该对象反映每个事件的影响。

这意味着State对象可以包含本身不能持久保存的值,而只是通过处理某些Event来设置的值。实际上,它们是从State中的持久值派生的缓存值。

在您的情况下,导致创建临时角色的操作将被捕获为角色上的Event。因此,您可以在eventHandler中创建临时角色,并将ActorRef放入新的State对象中。恢复演员后,它将重播该事件,而您的演员将重新创建临时演员。

如果您使用的是快照,那么我认为没有要求快照对象与State对象具有相同的类型,因此无需使用ActorRef和收到SnapshotOffer消息后重新创建它们。

答案 1 :(得分:1)

类型化持久性的一个设计目标是 State 可以从事件(或从快照和该快照之后的事件)中完全恢复。

一般来说,获得非持久状态的唯一方法是将 EventSourcedBehavior 包装在设置状态的 Behaviors.setup 块中。对此的一种选择是 var 中的某种可变状态(例如 setup 或(可能是独占或)可变集合),命令/事件/恢复处理程序对其进行操作。

一个更不可变的替代方法是在 setup 中定义一个不可变的装置,其中包括一个在 setup 中生成的子actor,用于管理非持久状态。您还可以将实体 ID 或其他至少对于实体的化身不可变的内容放入夹具中。