CQRS - 何时发送确认消息?

Kim*_*ble 13 domain-driven-design cqrs

示例:业务规则规定客户在下订单时应收到确认消息(电子邮件或类似信息).

假设a NewOrderRegisteredEvent从域中调度,并由发送确认消息的事件侦听器拾取.完成后,其他一些事件处理程序会抛出异常或其他错误,并回滚工作单元.我们现在已经向用户发送了回滚确认消息.

什么是解决这样的问题的"cqrs"方法,你想在一个工作单元提交后做某事?另一个复杂因素是重播事件.每当我重播录制的事件以构建新的视图/投影时,我都不希望重新发送旧的确认消息.

到目前为止我最好的理论:我刚刚开始研究cqrs迷人的世界,并想知道这是否会被作为一个传奇实现?如果一个saga就像一个状态机,每次转换只能进行一次,那么我想这会解决这个问题吗?我只是很难想象这将如何与命令总线和域事件一起使用.

Den*_*aub 16

  1. 事件应该仅在事务完成后发生.如果出现任何问题并且存在回滚,则从外部角度来看事件不会发生.因此,它根本不应该发表.虽然OrderRegistrationFailed必要时可以发布活动.

  2. 除非已成功执行命令,否则您不希望发送邮件.

    首先,为什么命令处理程序 - 在另一个答案中提出 - 将是错误的地方的几个原因:在某些情况下,命令处理程序将无法判断命令最终是否成功.让命令处理程序调用邮件发送也会将进程知识放入命令处理程序中,这会破坏SRM并使业务规则与应用程序层过于紧密.

    邮件应该在事后发送,即从事件处理程序发送.

    要防止在重放期间触发此处理程序,您可以不注册它.这与您测试应用程序的方式类似.您只需注册实际需要的处理程序.

    • 生产系统 - >注册所有事件处理程序
    • 测试 - >仅注册经过测试的事件处理程序
    • 重播 - >仅注册投影/非规范化处理程序

另一个 - 更松散耦合,虽然有点复杂 - 可能是有一个Saga句柄并向适当的有界上下文NewOrderRegisteredEvent发出SendMail命令(谢谢,Yves Reynhout,在问题的评论中指出这一点).

  • 事件日志只是存储事件以供参考和重放的表或文件.域模型的持久性仍然可以基于状态,例如在关系数据库中.可能的进一步步骤是不从状态存储和再现域模型,而是从事件本身存储和再现.这将是所谓的事件采购.在这种情况下,我们会谈到事件存储而不是事件日志.(当然,从技术上讲,事件日志也是商店.通常只在使用事件日志和使用事件源模式之间发生混淆). (3认同)