Параллелизм создания с CQRS и EventStore

Исходная информация: я использую для входа внешнего поставщика OAuth. Если пользователь входит во внешний OAuth, он может войти в мою систему. Однако этот пользователь может еще не существовать в моей системе. На самом деле это не проблема технологии, но я использую JOliver EventStore, потому что это того стоит.

Логика:

  1. Мне не дают руководство для новых пользователей. У меня есть только адрес электронной почты.
  2. Я проверяю свою модель чтения перед отправкой команды, если электронная почта пользователя существует, я запускаю команду входа с идентификатором, если нет, я запускаю команду CreateUser с сгенерированным идентификатором. Моя проблема связана с новым пользователем.
  3. Сохранение происходит в хранилище событий с новым идентификатором.

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

Что происходит. Поскольку новый идентификатор представляет собой гребенку Guid, нет никаких шансов, что хранилище событий узнает, что эти две команды CreateUser представляют одного и того же пользователя. К тому времени, когда они доберутся до модели чтения, модель чтения узнает об этом (поскольку у них одинаковая электронная почта) и сможет объединить две записи или предпринять какие-либо другие компенсирующие действия. Но теперь моя модель чтения не синхронизирована с хранилищем событий, которое все еще считает, что это два отдельных объекта.

Возможно, это не имеет значения, потому что:

  1. Воспроизведение событий окажет такое же влияние на модель чтения, так что все должно быть в порядке.
  2. Поскольку обе команды дублируют команды Create, они должны содержать одинаковую информацию, поэтому я ничего не теряю в хранилище событий.

Может ли кто-нибудь объяснить, как они справились с подобными проблемами? Если необходимо выполнить какое-либо компенсирующее действие, выдает ли служба модели чтения какую-либо компенсационную команду, когда понимает, что у нее есть повторяющаяся запись? Есть ли более простая методология, которую я не рассматриваю?


person swannee    schedule 29.06.2012    source источник


Ответы (1)


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

  • Выполните вызов OAuth.
  • Используя модель чтения, выберите между постоянным посетителем и новым посетителем на основе адреса электронной почты.
  • В случае нового посетителя отправьте командное сообщение RegisterNewVisitor, которое будет обработано и сохранено в хранилище событий.
  • Предположим, что происходит некоторый параллелизм, который для одного и того же адреса электронной почты вызывает два сообщения RegisterNewVisitor, каждое из которых содержит то, что система считает ключом, связанным с адресом электронной почты. Эти ключи (гайды) разные.
  • Обнаружьте эту проблему дублирования ключа в модели чтения и объедините обе записи модели чтения в одну запись.

Теперь, вместо объединения записей в модели чтения, почему бы не отправить ResolveDuplicateVisitorEmailAddress { Key1, Key2 } в модель домена, предоставив модель домена (кодифицированную форму бизнес-решения, которое необходимо принять) для решения этой проблемы. У вас даже может быть специальная модель чтения для решения подобных проблем, другая модель чтения просто получит своего рода событие DuplicateVisitorEmailAddressResolved и спроецирует его в соответствующие записи.

Слово предупреждения: вы задали технический вопрос, и я дал вам техническое, возможное решение. В общем, я бы не стал применять эту технику, если бы у меня не было какого-то бизнес-индикатора, в который стоит инвестировать (какова частота одновременного входа пользователя в систему в первый раз - возможно, решение этого таким образом - это просто способ игнорировать первопричину (ненадежный OAuth, отсутствие процесса регистрации нового посетителя и т. д.)). Существуют и другие технические решения этой проблемы, но я хотел дать вам наиболее близкое к тому, что у вас уже есть. Они варьируются от последовательной регистрации новых посетителей до сохранения в памяти прогноза посетителей, еще не включенных в модель чтения.

person Yves Reynhout    schedule 30.06.2012
comment
Я хочу сказать, что это решение относится к модели предметной области, если вы следуете этому курсу действий. - person Yves Reynhout; 30.06.2012
comment
Просто для полноты — это обсуждалось несколько раз — codebetter.com/gregyoung/2010/08/12/ - person Yves Reynhout; 01.07.2012
comment
Хорошо ответил, спасибо за ваши знания по этому вопросу. Я уверен, что на этот вопрос отвечали много раз, но с CQRS в целом трудно найти окончательные ответы, поскольку они очень разбросаны. Я также согласен с тем, что, возможно, слишком усложняю ситуацию, когда это не имеет большого значения. Возможно, мне не нужно ничего делать в этом случае, но сам случай вызвал больше вопросов о подходе в ситуациях, когда мне нужно решить эту проблему. Спасибо за ответ и за ссылку тоже. - person swannee; 02.07.2012