Как следует обрабатывать подписку и рассылку событий в контексте DDD - PullRequest
0 голосов
/ 06 ноября 2018

Насколько я понимаю, в DDD есть два типа событий. Бегал по одному и тому же процессу и по нескольким процессам.

Как следует обрабатывать подписку и отправку события?

Я приведу пример для размещения заказа. Когда вы размещаете заказ (1-й ограниченный контекст), вы должны обновить запас (2-й до н.э.).

Таким образом, в OrderAggregate у вас будет какой-то метод, который создает заказ, и в конце он добавит событие, например OrderPlacedEvent, в список Domain.Events.

Теперь при условии, что в первом ограниченном контексте вы отправите подтверждение по электронной почте. Кто должен уведомить SendEmailEventHandler о фактической отправке электронной почты?

Итак, кто несет ответственность за отправку события всем заинтересованным сторонам, в данном случае SendEmailEventHandler?

Более того, поскольку транзакция должна быть расширена до 2-го ограниченного контекста, кто должен отправлять событие? Я знаю шину сообщений, но если у вас ее нет?

Способ, которым я сейчас занимаюсь, заключается в том, что в моем Domain.Aggregate у меня есть метод AddEvent (событие IDomainEvent), который доступен классом AggregateRoot (базовый класс для агрегатов домена).

Когда агрегат что-то делает, он добавляет в этот список событие определенного действия.

StartOrder () => Метод OrderAggregate

OrderStartedEvent () => DomainEvent

В Application.Layer у меня есть UseCaseHandler (игровая площадка), где я вызываю агрегатные методы и репозитории (вот и все).

В инфраструктуре у меня есть репозиторий, который абстрагирует ORM и предоставляет только методы для добавления, обновления и удаления + метод, который будет получать агрегат по его идентификатору.

Из моего текущего проекта хранилище - это то, что отправляет события перед фиксацией.

Так вот как выглядит репо

   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;
            }
        }
    }

1-я Сомнение: Теперь эта часть представляет отправку, в которой я не совсем уверен. Должен ли репозиторий отвечать за диспетчеризацию, с моей точки зрения, это должно быть, но все же я не уверен?

А вот так выглядит приложение 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);
}

2-й Неизвестный: Где и кто должен обрабатывать подписку важнее?

1 Ответ

0 голосов
/ 06 ноября 2018

Вы хотите просмотреть Надежный обмен сообщениями с распределенными транзакциями , автор Udi Dahan.

Резюме: если вам нужна надежная доставка сообщений через границы, то вам необходимо спроектировать свою систему так, чтобы исходящие сообщения сохранялись в течение длительного времени с изменениями в модели домена, вам нужно повторить попытку подключения, которая будет отправлять все сообщения, которые не Принято считать, что вам нужна четкая семантика идентификации в ваших сообщениях, чтобы потребители могли распознавать дубликаты, и вам нужны потребители, которые делают разумные вещи при получении второй копии сообщения.

См. Также: Распределенные транзакции Life Beyond * , Пэт Хелланд.

...