1

因此,让我们以通常的 Order 示例为例。假设有一个富域模型,我们有一个 Order.place() 调用。这些天来执行与此操作相关的其他任务的方法似乎指向域事件。因此,假设此调用触发了“OrderPlaced”事件。放置事件后通常发生的事情是我们发送一封确认电子邮件,因此我们为此事件创建一个事件侦听器,并发送一封电子邮件。

很简单:Order.place() > 引发 OrderPlaced 事件 > EmailForOrderPlaced 监听器触发 > 电子邮件被发送

我们还有以类似方式工作的注册(User.register() > UserRegistered event raises > Registration listener fires > Email gets sent)

然而:

问题(一个虚构的任务 - 不一定有意义 - 但是很多实际的业务需求无论如何都没有):

现在我们希望将注册+订单功能合二为一,与常规的每次注册一封电子邮件+一封订单电子邮件相反,我们只想发送一封包含两者的电子邮件。这是一个复杂的问题,因此通常我们会创建一个域服务来执行此操作,但是如果我们调用 User.register(); 订单.place(); 现在它将像往常一样触发 2 个事件,向客户发送垃圾邮件(好吧,不是真的,但这是一个示例)

那么我们如何解决这个问题呢?显然,发送合并的电子邮件不是问题,因为我们可以在服务中为此引发事件,但这仍然给我们留下了原始的 2 封电子邮件。如果我在执行 2 个调用之前分离服务中的 2 个侦听器,那实际上意味着我必须了解它们的功能,并且每次添加新的侦听器时,我都必须返回服务分离那个,等等,有没有更好的方法可以无缝地做到这一点?

4

1 回答 1

1

你有几个选择。

首先,明确用例。例如,您可以在UserRegistered事件中添加一个布尔值,指示用户已注册为订单创建的一部分。这将允许电子邮件处理程序发送适当的电子邮件。

另一种选择是创建一个处理程序,为这两个事件发送电子邮件。由于无论如何都不应该立即发送电子邮件,因此处理程序在提交时确定在给定工作单元期间哪些事件已到达,并以此方式确定要发送的电子邮件类型。如果两个事件都已到达,则发送一封电子邮件,否则发送与收到的事件对应的电子邮件。为此,您必须确保处理程序具有每个工作单元的生命周期。

最后,深入挖掘,观察你必须在游戏中聚合 aUser和 an Order。理想情况下,尤其是在分布式场景中,您不应修改单个事务中的聚合。要实现需要修改聚合的用例,请创建一个也称为流程管理器的saga 。在 saga 中,每个聚合都在其自己的事务中被修改,并且作为事务的一部分,并发送一条消息以推进到下一步(在这种情况下有 2 个步骤)。saga 会收到一个名为RegisterUserAndCreateOrder. 然后它会注册用户,然后是订单,在两者都完成后,它会发送一封适当的电子邮件。请注意,用户和订单甚至可以同时创建。看看这里有关此事件驱动方法的更多信息。

于 2013-05-20T15:43:10.203 回答