CQRS/ES - обработка ошибок проекции
Я работаю над системой CQRS+ES, в основном использую инфраструктуру аксонов, но на самом деле этот вопрос относится к любой реализации. Итак, у меня есть обработчик команд и 1 или более обработчиков событий, работающих на разных JVM, контейнерах и т. Д., И в какой-то момент один из этих обработчиков сталкивается с ошибкой.
У нас есть два случая: "ожидаемая" бизнес-ошибка и "неожиданная" системная ошибка. Насколько я понимаю, мы сейчас находимся в асинхронном обработчике, и событие теперь является фактом, поэтому в действительности мы не можем напрямую откатить команду ни для одного случая (поскольку это может повлечь за собой откат ее в многочисленных других проекциях и прерывание CQRS).
Таким образом, мой вопрос заключается в том, должна ли такая ошибка быть "разрешена" каким-либо образом в бухгалтерской книге, то есть путем отправки новой команды "аннулирования", которая затем передается в прогнозы таким образом, что неудачное событие теперь разрешается?
В качестве примера, скажем, у нас есть команда, которая обновляет кредит клиента. Событие публикуется, одна проекция обновляет свою статистику "Всего кредитов", другая публикует обновление некоторого веб-сокета для пользовательского интерфейса и, наконец, еще одну, которая поддерживает состояние кредита - и этот последний обработчик завершается ошибкой. Должны ли мы отправить команду на откат бизнес-транзакции и снова вычесть кредит, снова обновить веб-сокет и т. Д.? И в случае аксона есть ли способ, которым это фиксируется как транзакция?
1 ответ
Я бы сказал, что принятие решения о том, что выполнение действия, то есть обработка команды - это нормально, всегда должно приниматься с помощью Командной модели / Агрегата. Агрегат, находящийся в неправильном состоянии для обработки действия, обычно приводит к "бизнес-исключению / ошибке".
Однако если вы принимаете решения при сбое обработки событий, вы добавляете некоторую логику принятия решений в службу обработки событий, которая в большинстве случаев, скорее всего, не имеет значения. Если такие службы обработки событий обновляют представления / модели запросов, но этого не происходит, я бы сказал, что это не является веской причиной для публикации "компенсирующей команды" в вашем агрегате для "отката / отмены события".
В вашем примере у вас есть обработчик состояния кредитования, который, как я предполагаю, обновляет модель запроса. Таким образом, я считаю, что проблема работы с исключением лежит внутри самой службы, а не путем выполнения компенсирующего действия.
С точки зрения Axon Framework, вы можете обернуть CreditStateEventHandler
в TrackingEventProcessor
и вызвать сброс на этом обработчике событий, вызвав TrackingEventProcessor#resetTokens()
функция. Это заняло позицию, что исключение, из-за которого ваш CreditStateEventHandler
конечно, из-за неправильного кодирования, в противном случае воспроизведение приведет к точно такому же исключению.