Nestjs 事件溯源 - 事件持久性

And*_*des 3 domain-driven-design cqrs event-sourcing typescript nestjs

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

Arn*_*ver 14

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

因此,对象模型允许一个干净的方式来创建CommandSagaQueryEvent对象,并为他们提供处理程序,定义AggregateRoot实体,并具有messagebuses用于发布,但没有更多。为您提供进行领域驱动设计的基础知识。

您如何集成它们完全取决于您。如果您在Github 上搜索“nest + cqrs”,您会发现许多不同的方法。一些选择是例如:

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

您关于持久事件的问题是指最后一点,并提示在 CQRS 之上实现事件源 (ES)。请注意,这样做完全是可选的。尽管 ES 具有许多有趣的特性,但您应该仅在您的应用程序需求有保证的情况下才应用此模式。ES 带来了额外的复杂性,这一点不容小觑。因此,绝对建议阅读优缺点(cqrs.nu常见问题解答是一个很好的入门)。请注意,您可以只实现 CQRS,然后在需要时添加 ES。

所以事件源(和事件持久性)不是 NestJS CQRS 模块的一部分。当你决定持久化你的事件时,你可以使用一个专门的数据库,比如Eventstore,或者你可以在你的关系数据库中实现它(参见 Postgres,例如 Postgres 中的事件存储PostgreSQL 事件源或成熟的项目message-db)。

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

NestJS 事件源 CQRS 架构概念

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

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