SuperAPI AI 工具集

event-sourcing

编程与开发

查看项目

更新于 10-16 11:29

技能介绍

用途

Event Sourcing 技能适用于已经明确选择采用事件溯源的函数式 TypeScript 项目,或项目中的特定限界上下文。它将应用状态的每次变更存储为不可变、仅追加的过去时领域事件序列。当前状态从不直接存储,而是对事件进行左折叠:state = events.reduce(evolve, initialState)。事件日志是真相来源,其他所有表示形式(聚合状态、读模型、搜索索引)都是派生的、可丢弃的投影,可通过重放事件重建。

该技能建立在另外三个技能之上:domain-driven-design 定义了 Decider(decide/evolve/initialState);hexagonal-architecture 将事件存储作为被驱动端口,并使用 CQRS-lite 拆分读取;typescript-strict 要求事件在出入存储的信任边界上采用 schema-first 与带品牌的 ID。

何时使用

事件溯源的复杂度很高,只有当变更历史本身就是领域的一部分时才值得采用。

适用:审计追踪是一等需求(金融、医疗、合规),需要回答“某日状态是什么、为什么”;需要时间查询或时间旅行,重建过去状态、重放复现缺陷;领域本质上是事件驱动的,业务以事件沟通且多个下游模型对其反应;需要对同一组事实建立多个独立演进的读模型,并希望通过重放历史事后新增读模型。

不适用:领域是 CRUD,即无实质历史的数据表单,应存储当前状态;只需要审计日志,则在当前状态表旁加一张仅追加历史表即可,成本低得多;只需要跨聚合副作用,应使用领域事件加 outbox 模式,那是事件驱动而非事件溯源;团队无相关经验且领域不要求,失败模式是半成品事件存储且无版本策略,后期难以更改。

复杂度阶梯:显式返回值 → 进程内领域事件 → outbox 模式 → 事件溯源。逐级攀升,通常只对某一个限界上下文采用。事件溯源不是 CQRS:CQRS 分离写模型与读模型,事件溯源选择事件作为写模型的存储;二者正交。实践中事件溯源几乎总是驱动 CQRS,因为存储的事件不适合查询,需要投影为读模型。

核心心智模型

  1. 事件是真相来源:不可变事实,以过去时命名,记录发生了什么与为什么,只能追加,纠正错误靠追加补偿事件。
  2. 状态是事件的左折叠:没有存储的“当前状态”,按需折叠 evolve 重建,称为 rehydration 或 replay。
  3. 流是一致性边界:一个聚合实例对应一个流,聚合不变式在其流内强制,追加使用乐观并发基于流版本,不依赖跨流事务。
  4. 读模型是可丢弃的派生:任何读优化视图都是另一种折叠,可删除并从事件零重建,从而事后新增报告变得简单。

词汇表:事件(不可变过去时事实,存储单元)、命令(尝试变更的请求,可能被拒绝,从不存储)、流(一个聚合实例的有序事件序列,一致性边界)、Decider(纯写模型 decide 与 evolve)、Rehydrate/replay(折叠重建状态)、投影(事件折叠为读模型)、快照(缓存折叠结果以避免重放长流,是优化而非真相来源)、事件存储(仅追加、有序、支持乐观并发的持久化,被驱动端口)、期望版本(命令决策所依据的流版本,用于检测并发写)。

主要能力

该技能覆盖:Decider 写模型(decide 返回显式 Decision:接受事件或拒绝原因;evolve 穷尽应用有效事件,不可能转换视为历史损坏并抛出错误)、命令处理循环(加载流事件及版本 → 折叠重建状态 → 纯业务决策 → 以期望版本追加,版本冲突则重试)、事件存储端口(最小契约 readStream 返回事件与版本,appendToStream 带 expectedVersion)、投影与读模型(inline 与 async 投影、重建、检查点、最终一致性)、事件版本化(upcasting、宽容读取器、弱 schema、流复制转换)、快照、生产关注点(GDPR/加密粉碎、幂等投递、可运维性、反模式目录)以及测试。

使用方式

技能以按需加载的深度资源组织,位于 resources/ 目录:when-to-use-event-sourcing.md 用于决定是否采用及与 CQRS、事件驱动架构、流处理、审计日志比较;modelling-events.md 用于发现与命名事件、事件粒度、事件数据;decider-and-rehydration.md 用于编写 decide/evolve、重建、命令处理循环、decider 组合;event-store.md 用于设计 EventStore 端口、Postgres schema、乐观并发、事件信封、TS/Node 工具生态;projections-and-read-models.md 用于读模型、inline 与 async 投影、重建、检查点、最终一致性;event-versioning.md 用于演进事件 schema;testing-event-sourced-systems.md 用于测试 decider、投影与 upcaster;production-concerns.md 用于快照、GDPR/加密粉碎、幂等投递、可运维性、反模式目录;references.md 用于核对理由与一手来源。

适用场景与限制

适用于金融、医疗、合规等审计追踪为一等需求的领域,或需要时间查询、时间旅行、多读模型、真正事件驱动的领域。限制:不适用于 CRUD;不应仅因需要审计日志就采用,可加仅追加历史表;跨聚合副作用应使用 outbox 模式;团队无经验且领域不要求时不建议采用。官方文本在此处被截断,EventStore 端口接口的后续内容、Postgres schema 等细节暂未提供。