【问题标题】:How should event subscription and dispatching be handled in the context of DDD在 DDD 的上下文中应该如何处理事件订阅和分发
【发布时间】:2018-11-06 13:30:48
【问题描述】:

据我了解,DDD 中有两种类型的事件。在同一进程下运行并跨多个进程运行。

应该如何处理事件的订阅和分发?

我将提供一个下订单的示例。当您下订单时(第一个有界上下文),您必须更新股票(公元前 2 年)。

因此,在 OrderAggregate 中,您将有一些创建订单的方法,最后它会将事件(例如 OrderPlacedEvent)添加到 Domain.Events 列表中。

现在假设在第一个有界上下文中,您将发送一封确认电子邮件。谁应该通知 SendEmailEventHandler 实际发送电子邮件?

那么谁负责将事件分发给所有相关方,在本例中为 SendEmailEventHandler ?

此外,由于事务应该扩展到第二个有界上下文,谁应该调度事件?我知道一个消息总线,但如果你没有呢?

我现在的设计方式是在我的 Domain.Aggregate 中有一个 AddEvent(IDomainEvent event) 方法,该方法由 AggregateRoot 类(域聚合的基类)提供。

当聚合做某事时,它会将来自特定操作的事件添加到该列表中。

StartOrder() => OrderAggregate 方法

OrderStartedEvent() => 领域事件

在 Application.Layer 中,我有一个 UseCaseHandler(操场),我在其中调用聚合方法和存储库(仅此而已)。

在基础设施中,我有一个存储库,它抽象了 ORM 并只提供了添加、更新和删除的方法 + 一个通过它的 id 获取聚合的方法。

根据我当前的设计,存储库是在提交之前分派事件的存储库。

这就是 repo 的样子

   protected override async Task AddAsync(TAggregate aggregate, CancellationToken token = default(CancellationToken))
   {
       using (ITransaction transaction = Session.BeginTransaction())
       {
            await Session.SaveAsync(aggregate, aggregate.Id, token);

            /// => dispatch domain.Event to all interested parties

            try
            {
                await transaction.CommitAsync();
            }
            catch
            {
                await transaction.RollbackAsync();

                throw;
            }
        }
    }

第一个疑问:现在这部分代表调度,我不完全确定。存储库是否应该负责调度,从我的角度来看应该但我仍然不确定?

这就是 Application UseCaseHandler 的样子

private IOrderRepository _orderRepository;

public async Task HandleAsync(CreateOrderRequest request, CancellationToken? cancellationToken = null)
{
    OrderAggregate aggregate = await _orderRepository.GetByIdAsync(request.Id);

    aggregate.CreateDraftOrder(); /// => adds the OrderPlacedEvent()

    await _orderRepository.CreateOrderAsync(aggregate);
}

第二个未知数:在哪里和谁应该更重要地处理订阅?

【问题讨论】:

    标签: architecture event-handling domain-driven-design messaging software-design


    【解决方案1】:

    您想评论 Udi Dahan 的 Reliable Messaging with Distributed Transactions

    总结:如果您需要跨边界可靠地传递消息,那么您需要设计您的系统,以便随着域模型的更改而持久地存储出站消息,您需要重试管道以发送所有未发送的消息得到确认后,您需要在消息中包含清晰的身份语义,以便消费者能够识别重复项,并且您需要消费者在接收到消息的第二份副本时做出明智的事情。

    另请参阅:Life Beyond Distributed Transactions,Pat Helland 着。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      • 2018-07-23
      相关资源
      最近更新 更多