【问题标题】:Detach event listeners for domain events? or how to stop executing otherwise required post events on specific use-cases分离域事件的事件监听器?或如何停止在特定用例上执行其他需要的发布事件
【发布时间】:2013-05-20 12:04:25
【问题描述】:

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

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

我们也有类似的注册方式 (User.register() > UserRegistered 事件引发 > 注册监听器触发 > 电子邮件被发送)

但是:

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

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

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

【问题讨论】:

    标签: oop domain-driven-design domain-model domain-events


    【解决方案1】:

    你有几个选择。

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

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

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

    【讨论】:

      猜你喜欢
      • 2023-03-14
      • 2016-01-07
      • 2019-11-26
      • 1970-01-01
      • 1970-01-01
      • 2018-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多