CQRS — может ли EventListener вызывать команду?

Я хочу использовать элементы шаблона CQRS в своем проекте. Интересно, правильно ли я делаю это с Command и Events. В чем я не уверен, так это в том, что событие может вызывать команду. Чтобы лучше показать, что я хочу сделать, я буду использовать диаграмму и пример.

Вот пример:

Пользователь вызывает TripCreateCommand. TripCreateCommandHandler выполняет свою работу и после успеха публикует TripCreatedEvent.

Теперь у нас есть два слушателя на TripCreatedEvent (порядок выполнения слушателей не имеет значения)

Первый слушатель (может быть выполнен после второго слушателя):

для каждого пользователя в trip.author.friends вызывать две команды (порядок команд важен)

  1. ОпубликоватьTripOnUserWallCommand
  2. SendNewTripEmailNotificationCommand
  3. SendNewTripPlatformNotification

Второй слушатель (может быть выполнен перед первым слушателем):

  1. ПубликацияTripOnUserSocials

А это примерная схема:

введите здесь описание изображения

Это хороший способ? Может ли EventListener вызвать команду или, может быть, мне следует сделать это каким-то другим способом?


person geek    schedule 20.01.2014    source источник


Ответы (2)


Ваш вопрос касается архитектуры, управляемой сообщениями, которая работает вместе с CQRS, но не связана с ней.

В любом случае, ваша диаграмма почти верна. Подписчик/обработчик событий (я предпочитаю эту терминологию) может отправлять новые команды через служебную шину, но это не правило, согласно которому вы должны всегда делать это. Я реализую довольно много функций непосредственно в обработчике событий, хотя, вероятно, было бы более чисто и надежно отправить новую команду. Это действительно зависит от того, что я хочу делать.

Обратите внимание, что обработчики сообщений (команды или события) не должны знать о других обработчиках. Они должны знать об автобусе, а автобус позаботится об управлении. Это означает, что в вашем приложении обработчики событий будут принимать шину как зависимость, создавать команду и отправлять ее через шину. Сам обработчик событий не знает, какой обработчик команд сгенерировал событие, и может «ответить» на него.

Обычно команды обрабатываются независимо, и вы не можете гарантировать порядок (если только они не обрабатываются синхронно), поэтому, возможно, вы хотите, чтобы вторая команда была выдана в результате обработки первой команды. Действительно, это может быть случай для саги.

Насколько я знаю, вы говорите только о том, чтобы делать что-то синхронно, поэтому ваш подход работает в этом случае, но, вероятно, он не масштабируется. Переход к асинхронной обработке нарушит этот поток выполнения. Однако ваше приложение может с этим справиться, не все должно быть твиттером.

Архитектура, управляемая сообщениями, не так проста, и в некоторых случаях (например, вам нужен немедленный ответ от серверной части) ее довольно сложно реализовать, по крайней мере, сложнее, чем при «стандартном» подходе. Так что, возможно, для этих конкретных случаев вы можете сделать это «по-старому».

Если вы беспокоитесь о развязке и тестировании, вы все равно можете спроектировать службы как обработчики сообщений, но использовать их напрямую, а не служебную шину.

person MikeSW    schedule 20.01.2014
comment
Спасибо за повтор! Масштабируемость — одна из самых важных вещей в моем проекте (я хочу иметь возможность горизонтального масштабирования моего приложения), поэтому мне определенно нужно обрабатывать команды асинхронно. Я хочу использовать асинхронность и ждать от С#, чтобы сделать это. - person geek; 21.01.2014

Не уверен, зачем вам нужны Команды для выполнения обновления информации на стене пользователя. Почему вы решили не использовать средство обновления модели представления для этой задачи.

Отправку электронного письма можно рассматривать как команду, но также можно легко рассматривать как просто еще одно обновление модели представления.

Непонятно, какова цель SendNewTripPlatformNotification, поэтому я не могу дать никаких предложений...

Кое-что из этого также может быть кандидатом на создание саги. Во-вторых, у меня на схеме не хватает вашего Домена, именно он должен отвечать за публикацию каких-либо событий, или вы считаете CommandHandler Доменом?

person Niklas Arbin    schedule 20.01.2014