You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS CQRS自定义EventPublisher后事件处理器未触发,如何实现事件转发?

解决方案

问题出在你替换EventBus的默认publisher后,原有的事件分发逻辑被覆盖——你的自定义MongooseEventStore仅完成了数据库存储,没有触发事件处理器的逻辑。要实现先成功存库再触发处理器,可以通过包装默认事件发布器的方式实现:

1. 修改自定义EventStore,整合默认发布逻辑

让MongooseEventStore注入默认的EventPublisher,在自身的publish方法中先完成数据库存储,再调用默认发布器的publish触发事件处理器:

import { Injectable, EventPublisher } from '@nestjs/cqrs';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
// 假设你已定义事件的Mongoose模型
import { EventDocument, Event } from './schemas/event.schema';

@Injectable()
export class MongooseEventStore implements EventPublisher {
  constructor(
    private readonly defaultPublisher: EventPublisher,
    @InjectModel(Event.name) private eventModel: Model<EventDocument>
  ) {}

  async publish<T>(event: T): Promise<void> {
    // 第一步:将事件存入数据库
    await this.persistEvent(event);
    // 第二步:调用默认发布器,触发事件处理器
    await this.defaultPublisher.publish(event);
  }

  // 批量发布逻辑同理
  async publishAll<T>(events: T[]): Promise<void> {
    for (const event of events) {
      await this.publish(event);
    }
  }

  // 实际数据库存储逻辑
  private async persistEvent(event: any) {
    const eventDoc = new this.eventModel({
      eventType: event.constructor.name,
      payload: event.payload,
      occurredAt: new Date(),
    });
    await eventDoc.save();
    // 若存库失败会抛出错误,中断后续发布,保证数据一致性
  }
}

2. 保持模块配置,确保事件处理器注册

你的UsersModule配置无需大幅修改,只需确保onModuleInit中正确注册事件处理器:

@Module({
  imports: [CqrsModule, DatabaseModule],
  controllers: [UsersController],
  providers: [
    TransactionsService,
    AccountRepository,
    MongooseEventStore,
    ...CommandHandlers,
    ...EventHandlers,
    ...accountsProvider,
  ],
})
export class UsersModule implements OnModuleInit {
  constructor(
    private readonly eventBus: EventBus,
    private readonly eventStore: MongooseEventStore,
  ) {}

  onModuleInit() {
    this.eventBus.publisher = this.eventStore;
    // 必须注册事件处理器数组
    this.eventBus.register(EventHandlers);
  }
}

关键逻辑说明

  • 一致性保障:如果数据库存储失败,persistEvent会抛出错误,后续的defaultPublisher.publish不会执行,避免出现「事件未存库但处理器已执行」的不一致情况。
  • 原生逻辑复用:通过注入默认EventPublisher,无需自行实现事件分发逻辑,直接复用NestJS CQRS的原生能力。

内容的提问来源于stack exchange,提问作者Paul Serre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 09:05:19