2012-02-26 2 views
18

Я пытаюсь реализовать свою собственную инфраструктуру CQRS с помощью Event Sourcing, чтобы узнать ее лучше. В качестве примера проекта я использую механизм блога, я знаю, что это может быть не совсем здорово, но я просто хочу работать над чем-то реальным.Проверка уникальности при использовании CQRS и источника событий

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

Я могу думать о двух «решениях».

  1. У вас есть совокупность Blog, в которой содержатся следы всех настроек, связанных с блогами, а также ссылки на все сообщения. Но проблема с этим в моих глазах заключается в том, что я должен обрабатывать связь между агрегатами в этом сценарии, а также каждый раз, когда мне нужно проверить уникальность shortUrl. Мне нужно прочитать все события из хранилища событий, чтобы создать все сообщения и это кажется сложным.
  2. Второй вариант, который у меня есть, - это когда событие срабатывает, а мой обработчик событий, который создает модель чтения, запускает повторяющееся короткое событие url, когда он замечает, что у него будут два коротких URL-адреса, указывающие на разные сообщения. Действительно ли, чтобы считываемая модель срабатывала при обнаружении ошибок?

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

+0

См. Http://stackoverflow.com/questions/2916899/how-to-handle-set-based-consistency-validation-in-cqrs –

ответ

0

Это зависит от того, что «бизнес» хочет осуществить. Если вы хотите, чтобы клиент (создатель команд) отвечал за выбор короткого URL-адреса, он должен иметь хранилище чтения, которое проверяет его уникальность. Когда пользователь вводит короткий URL-адрес, представление должно проверять, что короткий URL-адрес является уникальным и представляет ошибку проверки, если это не так. Всякий раз, когда сообщение сохраняется, событие публикует обновленную информацию (включая короткий URL-адрес), которая сохраняет синхронизируемое хранилище.

+1

Вот что я имею в виду: «Я знаю, что у меня будет эта проверка прежде чем я даже отправлю команду, прочитав из моего магазина чтения, чтобы проверить, действительно ли это при создании команды создания сообщения или команды обновления. " Но это не гарантия того, что он по-прежнему уникален, когда дело доходит до домена. Это очень маловероятно, когда вы создаете записи в блогах, но я думаю, что это интересный сценарий, который мне еще нужно выяснить, как решить, используя CQRS. Я имею в виду, как мне обрабатывать чек в домене? –

+0

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

1

Я бы пошел на службу домена, которая отвечает за создание уникальных ShortURL. Вы можете использовать транзакционную БД для реализации этого поведения. Обычно эта служба будет использоваться частью обработки команд агрегата BlogPost. Если есть дубликат ShortURL, вы можете запустить DuplicateUrlErrorEvent. Вы можете предварительно установить это в пользовательском интерфейсе (но не на 100%), создав тонкую модель запроса с использованием одного и того же источника данных, поэтому вы можете запросить, является ли короткий URL-адрес уникальным, прежде чем отправлять сообщение (как описано @ RyanR's ответ).

0

Я прочитал различные ответы на этот вопрос и связанный с ним вопрос.

Решение сводится к правильности. Если вы можете простить и принять несовершенное поведение для некоторой степени операции, ваша проблема намного проще решить, особенно при слабых гарантиях последовательности.

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

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

Если мы можем зафиксировать наши изменения в нашем магазине чтения, мы не нарушили ограничение уникальности (предполагая, что ваш магазин чтения применяет такое ограничение), и мы можем продолжить.

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

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

Был пример, когда банк разрешал пользователю перевыполнять свою учетную запись, поскольку у них есть надбавки для компенсации. Это вызывает вопросы, потому что казалось бы небрежным решить такую ​​проблему, даже ленив. Некоторые называют это умным. Я не знаю, что думать. У банка, вероятно, достаточно денег, чтобы покрыть его, чтобы они могли его игнорировать, но это не то, как мир в настоящее время работает. Во всяком случае, я отвлекся.

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

Смежные вопросы