диспетчер транзакций axon между командой и стороной запроса

#spring #spring-boot #cqrs #spring-transactions #axon

#spring #spring-загрузка #cqrs #spring-транзакции #axon

Вопрос:

у меня есть многомодульный проект spring boot maven с axon 4.4.2, иерархия проекта такая, как показано ниже:

приложение
--ядро
--на стороне команды
----команда-сторона-axon
----команда-сторона-отдых
--запрос--сторона
----постоянство на стороне запроса
----запрос на стороне rest

у меня есть пример создания нового каталога, как показано ниже, когда я отправляю запрос из command-side-rest, он всегда возвращает идентификатор в качестве ответа, даже если сбой сохранения на стороне запроса и данные не сохраняются в базе данных. Как я могу обрабатывать транзакции в этом случае? Я хочу, чтобы при сбое сохранения на стороне запроса событие не сохранялось в базе событий и вызывало исключение.

командная сторона — отдых

 @PostMapping
public String save(@RequestBody Catalog catalog) {
    return (String) commandGateway.sendAndWait(new CreateCatalogCommand(catalog));
}
  

на стороне команды-axon

 @CommandHandler
public void handle(CreateCatalogCommand cmd) {
    apply(new CatalogCreatedEvent(cmd.externalId, cmd.name));
}

@EventSourcingHandler
@Order(1)
public void on(CatalogCreatedEvent evt) {
    this.externalId = evt.externalId;
}
  

сохранение на стороне запроса

 @EventHandler
@Transactional(propagation = Propagation.REQUIRED)
@Order(2)
public void on(CatalogCreatedEvent event) {}
  

Ответ №1:

Я думаю, что могу дать вам некоторую информацию по этому вопросу, касающуюся вашего основного вопроса:

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

Ну, по сути, это означает, что вы вообще не хотите использовать CQRS. Что означает CQRS, так это разделение вашей командной модели (например, агрегата, обрабатывающего команду и публикующего событие) и моделей запросов (например, классы, обрабатывающие события, которые обновляют ваши модели).

Разделение этих двух дает вам то преимущество, что вы можете оптимизировать свои модели для обоих сценариев. Добавлено, что запрос на выполнение операции, он же команда, больше не влияет на то, действительно ли последующее событие может обновить модель запроса. Кроме того, этого не должно быть, если вы выполняете CQRS! Наличие такого точного разделения означает, что вы можете воссоздавать свои модели запросов, когда вам нужно, полностью отделенные от выполнения команд.

Таким образом, по сути, ваше хранилище событий, потому что одна модель, на которой вы можете основывать все модели, независима от другой. Вот почему использование событий при переходе к CQRS так хорошо работает с источником событий (в котором говорится о воссоздании вашей командной модели на основе событий, которые она опубликовала).

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

Если вы хотите, чтобы ваша модель командной строки и модель запроса были объединены в одной транзакции, вы все равно можете добиться этого, используя только SubscribingEventProcessor аксон in. Опять же, я бы обсудил с вашей командой / бизнесом, действительно ли это то, что вам нужно. Ознакомьтесь с некоторыми сообщениями на странице «обучение» AxonIQ, чтобы понять, почему CQRS, DDD и поиск событий могут быть полезны для вас.

Надеюсь, это проливает некоторый свет на ситуацию Aymen!