Как спроектировать события, на которые можно наложить вето, в event sourcing / eventuate

#event-sourcing

#event-sourcing

Вопрос:

Давайте предположим, что у нас есть простой вариант использования (java / микросервис / event sourcing / eventuate):

  • Микросервис A представляет пользовательскую сущность
  • Микросервис B обеспечивает синхронизацию наших пользователей с некоторым внешним пользовательским хранилищем (возможно, ldap и т.д.)

Давайте предположим, что B не может изменять имена пользователей по какой-либо технической причине, но A сам по себе допускает изменение имен пользователей.

Как это реализовать? В классических монолитах мы можем создавать что-то вокруг java.beans.VetoableChangeSupport. В микросервисе у меня возникают проблемы. Моей первой мыслью было разделить это на три события.

Сначала мы публикуем событие с надписью «Имя пользователя будет изменено». Вторым событием будет «Изменение имени пользователя отменено» всякий раз, когда микросервису B это не нравится. Третьим событием будет «Изменение имени пользователя прошло успешно».

Пока это будет работать. Но как мы это реализуем? Мне не нравится иметь монолит, который соединяет все микросервисы вместе. Мне нравится иметь некоторые концепции «плагинов». Пока мы не запускаем microservice B, никто никогда не накладывает вето, и мы автоматически должны запустить «Изменение имени пользователя прошло успешно». Но как только мы запустим микросервис B, мы должны проверить, нравится ли микросервису B накладывать вето на событие.

И как нам отличить «микросервис B не запущен» от «микросервис B в настоящее время отключен, но скоро вернется»? В первой ситуации мы не получаем вето. Во второй ситуации мы должны дождаться, пока B вернется снова, чтобы проверить ожидающие события «имя пользователя изменено».

Ответ №1:

Если вы не хотите зависимости от Microservice B, тогда я бы просто разрешил изменение имени изначально и рассматривал отказы от Microservice B как возможное исключение согласованности.

Итак, в микросервисе A вы делаете все возможное, чтобы гарантировать, что изменение не вызовет проблемы для того, с чем может синхронизироваться MS-B. Затем вы записываете событие «имя пользователя изменено».

Если MS-B не запущена, то на этом все, название изменено.
Если MS-B запущена и при попытке синхронизировать обновленное имя пользователя возникает проблема, вы переходите в режим исправления. Что именно это означает, будет зависеть от ряда факторов (насколько вероятно возникновение проблемы, каковы последствия и т.д.).
Вы могли бы приостановить MS-B и отправить электронное письмо, чтобы человек мог исправить ситуацию.
Или MS-B может выдать обратное изменение (другое «изменено имя пользователя» или «изменение имени возвращено обратно на: X» — все, что имеет смысл для вашего домена).

Если вы выдаете компенсирующие события, у вас будут некоторые дополнительные исключения, за которыми нужно следить … например, если User A измените их имя на User X , а User B затем измените их имя на User A . Если MS-B отменит первое изменение имени, вы получите повторяющиеся имена, если вы также не отмените второе изменение имени.
(Или, может быть, вы могли бы «заблокировать» старое имя пользователя на некоторое время, прежде чем его можно будет использовать повторно.)