Nestjs 中如何处理事件持久化?文档中并不清楚(阅读CQRS Recipe),我们应该如何持久化事件以及如何使用快照回复它们。也不清楚如何创建与写入侧分离的读取侧。
文档指出“为了促进 [CQRS] 模型,Nest 提供了一个轻量级 CQRS 模块。”,而这正是它所提供的。与 NestJS 的其余部分不同,小型 cqrs 对象模型并不那么固执己见,为实现者留下了很多架构决策。
因此,对象模型允许以一种干净的方式创建
Command
、Saga
、Query
和 Event
对象并为它们提供处理程序、定义 AggregateRoot
实体并拥有用于发布的消息总线,但仅此而已。为您提供领域驱动设计的基础知识。
如何整合它们完全取决于您。如果您在“nest + cqrs”上进行Github搜索,您会发现许多不同的方法。一些选择例如:
您关于持久事件的问题指的是最后一点,并提示在 CQRS 之上实现事件源(ES)。请注意,这样做完全是可选的。虽然 ES 具有许多有趣的功能,但只有当您的应用程序需求保证时,您才应该应用此模式。 ES 带来了额外的复杂性,这一点不应被低估。因此,绝对建议仔细阅读利弊(cqrs.nu常见问题解答是一个很好的开始)。请注意,您可以只实现 CQRS,然后在需要时添加 ES。
因此事件源(和事件持久性)不是 NestJS CQRS 模块的一部分。当您决定保留事件时,您可以使用专门的数据库,例如 Eventstore,或者您可以在关系数据库中实现它(请参阅 Postgres,例如 Postgres 中的事件存储、PostgreSQL Event Sourcing 或成熟的项目 消息数据库)。
使用事件溯源,您的设置可能类似于 Eliran Natan 的好文章 Event-Sourcing with NestJS 中所描述的内容:
在此设置中,您必须进行投影来加载通常为架构读取端具有非规范化视图的关系数据库。如果没有 ES,这可能不需要,您可以使用 ORM 或直接 SQL 查询来用适当的数据来填充您的
Query
对象。
就是这样。最后一个技巧是永远不要从写入端代码直接调用读取端逻辑(这会带来麻烦,因为它会破坏命令/查询分离)。
在这里聚会晚了,但如果您仍在寻找事件持久性的解决方案:@ocoda/event-source是一个 NestJS 模块,它提供了 @nestjs/cqrs 提供的基本功能,但还添加了存储和检索事件(和快照)的必要工具。另一方面,它仍然缺乏 Saga 和进行事件重播的内置方式。
完全披露:我是该库的创建者。