Nestjs 事件溯源——事件持久化

Nestjs Event Sourcing - Event Persistence

Nestjs 是如何处理事件持久化的?文档中并不清楚(阅读 CQRS Recipe),我们应该如何持久化事件以及我们如何使用快照回复它们。还不清楚如何创建与写入端分开的读取端。

文档指出 “为了促进 [CQRS] 模型,Nest 提供了一个 轻量级 CQRS 模块。”,这正是它提供什么。与 NestJS 的其余部分不同,小型 cqrs 对象模型并不是那么自以为是,为实现者留下了很多架构决策。

因此对象模型允许一种干净的方式来创建 CommandSagaQueryEvent 对象并为它们提供处理程序,定义 AggregateRoot 实体和用于发布的消息总线,但仅此而已。为您提供领域驱动设计的基础知识。

如何整合它们完全取决于您。如果您在 'nest + cqrs' 上执行 Github search,您会发现许多不同的方法。一些选择例如:

  • 直接在控制器中而不是在应用层服务中创建命令。
  • 命令 return 无数据与 return 仅错误与 return 仅写入数据。
  • 聚合根和 DB/ORM 实体相同 class(不是 DDD 最佳实践)。
  • 通过事件总线手动发出的事件与通过 mergeObjectContext 在聚合根上发出的事件。
  • 读端和写端模型的单一数据库与多个数据库。

你关于持久化事件的问题指的是最后一点,并提示在 CQRS 之上实现事件源 (ES)。请注意,这样做完全是可选的。虽然 ES 具有许多有趣的功能,但您应该只在应用程序要求允许的情况下应用此模式。 ES 带来了额外的复杂性,这一点不应被低估。因此,绝对建议仔细阅读利弊(cqrs.nu FAQ 是一个很好的开始)。请注意,您可以只实现 CQRS 并在以后需要时添加 ES。

所以事件源(和事件持久化)不是 NestJS CQRS 模块的一部分。当您决定保留您的事件时,您可以使用专门的数据库,例如 Eventstore or you can implement it in your relational db (see for Postgres e.g. Event Storage in Postgres, PostgreSQL Event Sourcing or full-blown project message-db).

使用事件溯源,您的设置可能类似于 Eliran Natan 的好文章 Event-Sourcing with NestJS 中描述的内容:

在此设置中,您必须进行 投影 以加载一个 - 通常 - 具有非规范化视图的关系数据库,用于架构的读取端。如果没有 ES,这可能就不需要了,您可以使用 ORM 或直接 SQL 查询来为您的 Query 对象添加适当的数据。

就是这样。最后一个提示是永远不要从写端代码直接调用读端逻辑(这是一个麻烦的秘诀,因为它破坏了 command/query 分离)。