22

目前,我们正在构建一个基于 CQRS 和领域驱动设计原则的新架构。我们现在正在讨论我们应该如何处理外部沟通。为了使问题更具体,我使用了在客户创建订单时发送 SMS 通知的示例。

客户端创建一个由关联的命令处理程序处理的 NewOrderCommand。处理程序在域模型中创建一个新的 Order 对象,该对象生成一个 NewcustomerCreatedEvent。该对象被保存在事件存储中,并且该事件被发布给所有的监听器。

到目前为止一切都很好,但现在是个问题。我们应该在哪里发送短信通知?

我们的第一直觉告诉我们应该使用事件侦听器将其发送出去,该侦听器侦听 NewCustomerCreatedEvent 并发送消息。这种方法的问题在于,SMS 的发送也是我们业务逻辑的一部分。我们正在销售托管服务,因此我们的客户应该能够看到代表他们发送的所有 SMS 消息。因为消息的发送发生在域之外,我们无法做到这一点。

所以我们创建了一个 SMS 域,现在当事件侦听器收到 NewCustomerCreatedEvent 时,事件处理程序创建一个新命令 SendSmsMessageCommand,它将在我们的域中创建一个新的 SMSMessage 对象,发送 SMS 通知并创建一个 SmsSent 事件,我们使用它来创建看法。

起初我们在域模型中发送 SMS 消息,但我们意识到这可能会带来一些问题。假设在发送 SMS 之后发生了一些事情(抛出异常)并且事务被回滚。我们的域完全支持这一点,所以数据方面我们没问题,但是 SMS 消息已经发送,所以当重新发送命令时,SMS 通知将再次发送。

我们正在考虑在 SmSSent 事件上发送 SMS,但这有点奇怪,因为该事件表示消息已发送但尚未发送。

上面的例子给我们带来了一个问题,在 CQRS 和领域驱动设计概念中如何处理外部通信?我们不仅在谈论发送 SMS 通知,而且还在谈论向外部计费系统发送发票以及与外界进行所有其他类型的通信。我们应该在域中这样做,因为它是业务逻辑,还是应该始终基于事件处理程序中的事件来这样做?如果我们这样做,是否可以使用事件表明消息在实际尚未完成时已发送?

希望你们已经处理过这种情况,并可以就这个问题给我们一些建议。

4

2 回答 2

2

我认为 SMS 消息的域对象不是必需的。您只需要报告发送给客户的短信,对吗?SMS 消息未在任何域逻辑中使用,对吗?

所以我会让处理程序发送一条 SMS,然后发布另一个事件,说明发送了一条 SMS,并让一个事件处理程序侦听 SMS 发送的消息并在读取模型中具体化该信息,以便客户可以查看它们。

于 2011-06-09T20:22:43.303 回答
0

您可以使用 Saga 或 Microsoft 所称的 Process Manager。这基本上是监听改变 saga 状态的事件,并根据 saga 中实现的状态逻辑发出命令。

在您的情况下,这将是一个两种状态的传奇,它同时等待 CustomerCreatedEvent 和 OrderCreatedEvent,并且,如果您有专门的有界上下文进行通信,或者通过接口调用基础设施服务,或者发出命令发送短信,发送短信。

在这里你可以找到微软关于 saga/process manager 模式的文章:

https://msdn.microsoft.com/en-us/library/jj591569.aspx

还有两篇包含实现的文章:

http://danielwhittaker.me/2015/03/31/how-to-send-emails-the-right-way-in-a-cqrs-system/

http://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-ii-of-ii/

于 2015-10-12T19:47:06.590 回答