场景: (User Service)

更新用户操作包含更新用户基本属性和分配角色,由两个线程分别执行,当一个线程执行成功另一个执行失败时,需要回滚整个处理流程

 

解决方案:使用CQRS事件溯源回滚聚合根到指定状态

事件溯源(Event Source):

事件溯源能够保证对应用状态所有的改变被当作一系列的事件存储起来,我们不仅仅能查询这些事件,我们还能利用这些事件记录还原应用过去的状态,并作为自动调整状态以应对追溯性变化的基础.

逻辑分析:        

更新用户无论是更新用户基本属性还是分配角色,我们期望是从上一次对这个聚合根实例状态的改变节点开始,

比如第一次创建一个UserAggregate实例 {name=zhngsan,phone=123,assignedRoleList=[r01,r02,r03]},后来更新了这个聚合根实例将assigedRoleList属性从[r01,r02,r03]更新为[r01,r04]此时UserAggregate变为{name=zhngsan,phone=123,assignedRoleList=[r01,04]},假如又要对这个聚合根实例更新,那么我们期望从上一次assigedRoleList属性为[r01,r04]这个节点开始更新.        

       怎样得到过去某个状态改变的聚合根实例?        

       我们尝试通过调用AXON load()方法得到一个UserAggregate,测试发现无论用这个方法名的任何重载方法得到的聚合根实例状态都为初始化状态,也就是该聚合根第一次被创建的状态,这与我们的期望不相符,于是想到既然事件溯源 '能利用这些事件记录还原应用过去的状态'

不妨从Event Source下手,通过查阅它的API发现AXON提供了EventStore组件,该组件提供一种机制从底层事件存储器打开事件流,至此我们有了新的方法通过EventStore组件获取DomainEventStream表示由聚合发布的历史事件流,然后加入逻辑判断从事件流中过滤出当前业务最关注的事件,最终结合初始化状态聚合根实例和事件还原得到过去发生这个事件的聚合根实例.        

       比如上面给出的例子(不考虑程序真实执行过程中所产生的所有事件)对UserAggregate聚合根的改变一共产生3个事件,

      1.UserCreatedEvent {name=zhngsan,phone=123}

      2.RoleAssignedEvent {assignedRoleList=[r01,r02,r03]}

      3.RoleAssignedEvent {assignedRoleList=[r01,r04]},此时我们期望从上一次assigedRoleList属性为[r01,r04]这个节点开始更新,只需,

      a.调用AXON load()方法得到一个初始化状态UserAggregate实例 {name=zhngsan,phone=123,assignedRoleList=[r01,r02,r03]},

      b.调用AXON EventStore readEvent()方法获取事件流,并通过版本号和事件类型(RoleAssignedEvent.class)过滤得到上一次最新的分配角色事件RoleAssignedEvent {assignedRoleList=[r01,r04]},

      c.更新a b两步共同的assignedRoleList属性得到上一次最新的分配角色UserAggregate聚合根实例 {name=zhngsan,phone=123} 2.RoleAssignedEvent {assignedRoleList=[r01,r04]}.

      回到我们最开始的话题,怎样回滚整个处理过程?

    通过对上面怎样获取过去某个状态改变的聚合根实例的了解,不难发现回滚整个处理过程只是一个体力活,最关键的问题已经得到解决,所以就不详细介绍了.

posted on 2019-08-28 18:25  lshan  阅读(1311)  评论(0编辑  收藏  举报