首页 > 解决方案 > 在 NestJS CQRS 配方中处理“事件溯源”的首选方式

问题描述

我一直在尝试找出在使用 NestJS CQRS 配方(https://docs.nestjs.com/recipes/cqrs)时进行“事件溯源”的首选方式。

在过去的几周里,我一直在研究 NestJS 框架,并且喜欢它的各个方面。除了在某些领域非常薄的文档。

NestJS 对如何实现“事件溯源”并没有真正的看法,或者我遗漏了一些明显的东西。

我的主要问题是:保持事件本身最简单的方法是什么?

现在,我的事件看起来很基本:

import { IEvent } from '@nestjs/cqrs';

export class BookingChangedTitleEvent implements IEvent {
    constructor(
        public readonly bookingId: string,
        public readonly title: string) {}
}

我最初的想法是使用 TypeORM ( https://docs.nestjs.com/recipes/sql-typeorm ) 并使我的每个事件不仅实现IEvent,而且使其继承 TypeORM @Entity()

但是,每个事件都会有一个表 (SQL) 或集合 (NoSQL),因此无法读取发生在单个聚合中的所有事件。我错过了什么吗?

另一种方法是将每个事件转储到 JSON,这听起来很容易。但是我将如何IEvent从数据库中加载对象类呢?(听起来我正在实现自己的 ORM)

标签: node.jstypescriptnestjscqrsevent-sourcing

解决方案


所以我正在做类似的事情并使用 postgres,它在 TypeORM 白话(参考)支持 json('simple-json' )。无论好坏,我的事件实体看起来像:

@Entity()
export class MyEvent {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  name: string;

  @Column('simple-json')
  data: object;

  @CreateDateColumn({type: 'timestamp'})
  created_at: Date;
}

需要注意的是,我仅将持久事件用于审计跟踪以及我尚未构建的潜在预测的灵活性。您完全可以使用 TypeORM 在 postgres 中查询 JSON,例如。.where('my_event.data ::jsonb @> :data', {data: {someDataField: 2}}),但我的理解是查询您的事件以获取当前状态有点缺少 CQRS 的意义。最好在新的投影表中建立聚合或更新一个巨大的投影。

我对我目前坚持我的活动的方式很好,但它肯定不是 DRY。我认为使用通用saveEvent方法扩展基类或使用 EventHandlerFactory 类在其构造函数中获取存储库会更干净一些,而不是将存储库注入每个处理程序。

也许有人在那里有一些好的想法?


推荐阅读