29.Axon框架-事件(七)

40 阅读3分钟

Axon框架-事件(七)

1.事件的不可变特性的问题

在快速变化的需求中,事件定义也可能随时间迭代。事件存储是只读且仅支持追加的数据源,因此无论事件何时添加(多个版本的事件),应用都必须能够读取所有事件(应用必须能够处理多个版本的事件)

1768486435560.png

2.什么是事件升级

事件升级最初是面向对象编程的概念,指子类在需要时自动向上转型为其父类,该概念同样适用于事件溯源。事件升级即将事件从原始结构转换为新结构。与OOP的自动向上转型不同,事件升级无法完全自动化(旧事件不了解新事件的结构),需手动编写升级器(Upcaster),明确旧结构到新结构的转换规则

3.什么是Upcaster

Upcaster是一类特殊组件:接收版本为x的输入事件,输出零个或多个版本为x+1的新事件。此外,Upcaster以链式方式执行——前一个Upcaster的输出作为下一个Upcaster的输入。这种设计支持事件的增量更新:为每个新事件版本编写独立Upcaster,确保升级器小巧、解耦且易于理解

Axon框架中事件升级器的基础接口Upcaster,接收IntermediateEventRepresentation流作为输入,返回IntermediateEventRepresentation流作为输出。升级过程不会直接返回最终结果,而是通过堆叠中间事件表示,将多个版本间的升级函数链式串联。当最终结果被拉取时,才会对序列化事件执行实际的升级操作

1768486688723.png

4.事件升级的核心优势

事件升级最大的价值在于支持非破坏性重构——事件的完整历史记录保持不变,不会因结构变更丢失数据,这与DDD中事件溯源需保留完整业务轨迹的核心要求完全契合

5.配套组件

RevisionResolver

为了让Upcaster识别接收的序列化对象版本,事件存储会记录事件的版本号和全限定类名。版本号由序列化器中配置的RevisionResolver生成

1768488097544.png

IntermediateEventRepresentation

Axon的Upcaster不直接操作EventMessage,而是通过IntermediateEventRepresentation工作

1768488142214.png

6.Upcaster常见实现类和功能

介绍

1768488298907.png

不同序列化格式的处理

事件存储中可能存在多种序列化格式的事件(因使用了不同的Serializer实现)。升级时需注意IntermediateEventRepresentation的格式(会影响Upcaster实现),可通过canConvertDataTo验证中间表示是否支持目标类型

SingleEventUpcaster

1768488367955.png

EventMultiUpcaster与EventTypeUpcaster

1768488490551.png

特殊实现

1768488576945.png

7.实战

目标

1768488605192.png

适配Jackson序列化器

public class ComplaintEvent1_to_2Upcaster extends SingleEventUpcaster {

   private static final SimpleSerializedType TARGET_TYPE =
           new SimpleSerializedType(ComplaintEvent.class.getTypeName(), "1.0");

   @Override
   protected boolean canUpcast(IntermediateEventRepresentation intermediateRepresentation) {
      return intermediateRepresentation.getType().equals(TARGET_TYPE);
   }

   @Override
   protected IntermediateEventRepresentation doUpcast(
           IntermediateEventRepresentation intermediateRepresentation
   ) {
      return intermediateRepresentation.upcastPayload(
              new SimpleSerializedType(TARGET_TYPE.getName(), "2.0"),
              com.fasterxml.jackson.databind.JsonNode.class, // Jackson序列化后的事件数据类型
              event -> {
                  // 强制转换为ObjectNode,添加description字段
                  ((ObjectNode) event).put("description", "no complaint description");
                  return event;
              }
      );
   }
}

8.执行顺序

介绍

选择Upcaster类型并实现后,需将其配置到应用中。核心注意事项:Upcaster必须按顺序执行。事件可能经历多次格式迭代,每个迭代版本都有对应的升级需求——由于单个Upcaster仅支持一个版本到下一个版本的转换,保持升级器的执行顺序至关重要

EventUpcasterChain是维护Upcaster顺序的核心组件,事件存储通过它将所有升级函数附加到事件流。多数场景下无需直接操作EventUpcasterChain

原生API

1768488766613.png

SpringBoot

1768488777989.png