如何基于事件溯源实现复杂表单的命令与事件?Axon框架CQRS/ES实践咨询
针对你想用Axon框架实现CQRS与事件溯源(ES)来处理六步招聘流程表单的需求,我结合Axon的核心特性,整理了一套贴合你业务场景的落地方案:
1. CQRS职责拆分
首先明确读写分离的边界:
- 命令端(写侧):负责处理所有管理员操作和表单更新,通过Axon的
CommandBus分发命令,由聚合(Aggregate)处理并生成事件。核心操作包括:步骤负责人分配、备注添加、候选人审核、通知开关调整、标签分配、表单差异更新。 - 查询端(读侧):专注于历史统计数据生成、表单变更追踪、当前表单状态查询,通过Axon的
QueryBus处理查询请求,基于事件投影(Projection)实现高效读操作。
2. 事件溯源(ES)核心设计
事件溯源的核心是用事件记录所有状态变更,聚合的状态完全由事件重构而来。针对你的招聘流程,需要定义以下核心事件:
CandidateStepAssignedEvent:记录步骤负责人分配NoteAddedEvent:记录备注添加CandidateStepApprovedEvent:记录步骤通过CandidateStepRejectedEvent:记录步骤拒绝NotificationToggledEvent:记录短信/邮件通知开关变更TagAssignedEvent:记录标签分配FormFieldUpdatedEvent:记录表单字段差异更新
这些事件会被Axon的EventStore持久化,后续可以通过事件回放重构任意时间点的聚合状态。
3. 表单差异更新的处理
由于UI仅传输差异内容,需要针对性设计命令和事件:
- 定义
UpdateFormDifferencesCommand,包含招聘申请ID、差异字段键值对(比如{"step3.status": "pending", "step3.comment": "补充材料"}) - 在聚合的
@CommandHandler中处理该命令,验证差异的合法性后,生成FormFieldUpdatedEvent - 聚合通过
@EventSourcingHandler应用该事件,仅更新对应的字段,避免全量覆盖状态
这种方式既减少了网络传输量,也符合事件溯源“记录每一次变更”的原则。
4. 管理员操作的命令与事件建模
每个管理员操作都对应独立的命令和事件,保证单一职责:
- 分配负责人:
AssignStepOwnerCommand→ 生成CandidateStepAssignedEvent - 添加备注:
AddNoteCommand(包含步骤ID、备注内容)→ 生成NoteAddedEvent - 审核候选人:
ApproveCandidateStepCommand/RejectCandidateStepCommand→ 分别生成对应通过/拒绝事件 - 调整通知开关:
ToggleNotificationCommand(指定通知类型:SMS/EMAIL,开关状态:开启/关闭)→ 生成NotificationToggledEvent - 分配标签:
AssignTagCommand(支持批量添加)→ 生成TagAssignedEvent
每个命令处理方法中要做必要的业务校验(比如只有对应步骤的负责人才能审核),校验通过后再发布事件。
5. 历史统计与变更追踪实现
利用Axon的事件查询能力和投影机制来实现:
- 历史统计:可以通过
EventStore.query()方法查询指定日期范围内的事件,比如统计某一周内各步骤的通过/拒绝数量;也可以构建AggregateStatisticsProjection投影,监听所有审核事件,实时更新统计数据到只读表,查询时直接读取投影表提升性能。 - 变更追踪:构建
CandidateChangeHistoryProjection,监听所有相关事件,将事件详情(操作人、时间、变更内容)存入变更记录表,支持按候选人ID、时间范围查询完整变更 timeline。
6. 关键细节注意
- 聚合的设计:以招聘申请为聚合根,聚合根ID用唯一的招聘申请ID,所有操作都围绕这个聚合根展开,保证聚合内的事务一致性。
- 通知逻辑:可以通过Axon的
EventGateway发布NotificationToggledEvent后,由单独的事件处理器监听该事件,调整后续通知的发送规则(比如关闭邮件通知后,不再发送相关邮件)。 - 标签管理:聚合内维护标签集合,支持添加/移除标签,对应的事件要记录标签的增删操作,方便追踪标签变更历史。
内容的提问来源于stack exchange,提问作者Wojciech Marusarz
相关产品推荐
相关产品推荐

