让我们假设一个使用Akka Typed实现的应用程序有一个持久化的参与者。(或非持久性)子参与者,每个子参与者都有一个唯一的ID,这些ID是持久性状态的一部分。持久性参与者还需要某种与其子参与者通信的方式,但我们不想持久化子级的ActorRef
,因为它们实际上并不是状态的一部分。在恢复时,持久化参与者应该基于恢复的状态重新创建它的子级。这听起来并不像是一个非常不寻常的用例,我想知道什么是最简洁的实现方式,我可以在命令处理程序的andThen
Effect
中创建子角色,但是这样就没有办法从那里保存子对象的ActorRef
了。在持久参与者中很难有非持久状态(在本例中,它可以用于存储临时子对象ActorRef
)我提出的一个解决方案是使用一种“代理”角色来创建子对象,保存ID并且在每次需要创建一个新的子节点或向一个现有的子节点发送消息时联系它。我对此百感交集,如果有人能给我指出一个更好的解决方案,我将不胜感激。
2条答案
按热度按时间qnzebej01#
如果你没有使用快照,那么持久化机制不会存储
State
对象,它会存储导致State
对象的Event
序列。在恢复时,它只会按照它们发生的顺序重放那些Event
,而你的eventHandler
将返回一个修改过的State
对象,反映每个事件的效果。这意味着
State
对象可以包含本身不是持久化的值,而只是通过处理某些Event
来设置的值。实际上,它们是从State
中的持久化值派生的缓存值。在您的示例中,导致创建临时参与者的操作将被捕获为参与者上的
Event
。因此,您可以在eventHandler
中创建临时参与者,并将ActorRef
放在新的State
对象中。当恢复参与者时,它将重播该事件,您的参与者将重新创建临时参与者。如果您使用快照,那么我认为不需要快照对象与
State
对象的类型相同,因此您可以在没有ActorRef
的情况下对状态进行快照,并在收到SnapshotOffer
消息时重新创建它们。wfauudbj2#
类型化持久性的一个设计目标是,
State
可以从事件(或者从快照和自该快照以来的事件)中完全恢复。一般来说,拥有非持久状态的唯一方法是将
EventSourcedBehavior
封装在一个设置状态的Behaviors.setup
块中。一种选择是在setup
中放置某种可变状态(例如var
或(可能是互斥或)可变集合),由命令/事件/恢复处理程序操作。一个更不可变的替代方法是在
setup
中定义一个不可变的fixture,它包含一个在setup
中产生的子actor来管理非持久状态。您还可以将实体ID或其他至少对于实体的这个化身不可变的东西放入fixture中。