Синхронный ответ AXON framework

Я новичок в платформе AXON и использую ее для наших разработок. У нас есть требование, в котором команда (сторона команды) создается для сохраняемых данных, поскольку запускается то же событие, которое потребляется на стороне запроса. Теперь нам нужно получить ответ на сторону команды со стороны запроса, в котором говорится, успешно ли сохраняется запись в базе данных (настраиваемое сообщение об успешном завершении) или, если не удалось, то причину сбоя (настраиваемое сообщение об исключении в качестве ответа). Пожалуйста, помогите, если есть какой-либо способ реализовать такой сценарий.

Здесь командная сторона и сторона запроса - это 2 разных микросервиса, и мы используем Rabbit Mq для техники, управляемой событиями.

заранее спасибо


person Jaspal    schedule 21.11.2018    source источник


Ответы (4)


Я думаю, что вы спрашиваете, есть ли способ обработки команды и события в одной транзакции?

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

Лучше всего для агрегата с обработчиком команд иметь всю доступную информацию, чтобы решить, может ли команда быть успешно обработана, и когда применяется событие, это сигнал о том, что оно произошло, а другие службы ( сторона запроса в этом случае) должны быть проинформированы. Для модуля запросов не рекомендуется отменять это («вы говорите, что это произошло, а я говорю, что нет»). Если на стороне запроса есть ошибка, вы ее исправляете и воспроизводите событие повторно.

Если это действительно ошибка в обработчике событий, о которой должна знать вся система, это действительно отдельное событие. Вы можете применить такое событие прямо к шине событий и уведомить всю систему. Что-то вроде этого:

 @Autowired
 private EventBus eventBus;

 (...)

 CatastrophicFailureEvent failureEvent = new CatastrophicFailureEvent("OH NO!");
 eventBus.publish(GenericEventMessage.asEventMessage(failureEvent));
person Mzzl    schedule 22.11.2018

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

Если вам нужно проверить, существует ли уже пользователь, вам нужно сделать это на стороне команды в вашем агрегате. Агрегат может хранить список всех существующих имен пользователей и генерировать исключение, если дана недопустимая команда. Ответ на команду (совет: использование метода sendAndWait () в CommandGateway возвращает ответ) затем можно использовать в качестве системы для информирования пользователя об успехе / неудаче его действия.

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

Командная сторона:

  1. Запрос от внешнего интерфейса обрабатывается классом контроллера и создает соответствующую команду
  2. Вышеупомянутая команда вызывается и обрабатывается обработчиком команд, который создает соответствующее событие или генерирует исключение, если пользователь уже существует.
  3. Вызывающий команду информируется об успешном выполнении команды или об обработке исключения и об ошибке, показываемой пользователю.
  4. Вышеупомянутое событие публикуется через шину событий rabbit mq, если команда была успешной.

Сторона запроса:

  1. Событие, опубликованное на шаге 4, обрабатывается обработчиком событий на стороне запроса. Никаких проверок или валидаций не требуется, поскольку они уже были обработаны на стороне команды.
person Ostecke    schedule 04.12.2018

@Mzzl Серия мероприятий

Командная сторона:

1. Request from frontend handled by a Controller class and creates an corresponding command
2. The above command is invoked and handled by a command handler which in return create corresponding event
3. The above event is then published through rabbit mq event bus.

Сторона запроса:

4. The event that is published in the step 3 is consumed by the event handler in query side.
5. The event handler has the logic to perform db transaction (lets assume add a user). Once a user is added then a success message or failure message (lets assume user already available in the DB so could not create duplicate entry) should flow from query side to command side and eventually back to UI as a repsonse.
person Jaspal    schedule 27.11.2018
comment
Если у вас есть новый вопрос, задайте его, нажав кнопку Задать вопрос. Включите ссылку на этот вопрос, если она помогает понять контекст. - Из отзыва - person common sense; 27.11.2018
comment
@Mzzl, не могли бы вы помочь с вышеуказанным вопросом? - person Jaspal; 28.11.2018

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

В этом примере вы можете видеть, что он использует SubscriptionQueryResult в сочетании с QueryUpdateEmitter (см. здесь)

Обычно вы подписываетесь на изменения на стороне запроса до того, как команда будет выпущена, и вы будете блокироваться после выполнения команды до тех пор, пока сторона запроса не отправит уведомление, когда оно будет актуальным.

Таким образом вы можете избежать возможной согласованности.

person Sylvain    schedule 12.12.2018