Я использовал два подхода в моих проектах, в зависимости от требований:
- Синхронный, внутрипроцессный Readmodels.После того, как события сохраняются, в том же времени существования запроса, в том же процессе, Readmodels получают эти события.В случае сбоя Readmodel (ошибка или перехватываемая ошибка / исключение) ошибка записывается в журнал, и что Readmodel просто пропускается, а следующий Readmodel получает события и так далее.Затем следуйте Сагам, которые могут генерировать команды, которые генерируют больше событий, и цикл повторяется.
Я использую этот подход, когда влияние сбоя Readmodel является приемлемым для бизнеса, когда готовностьДанные Readmodel важнее, чем риск сбоя.Например, они хотели, чтобы данные были немедленно доступны в пользовательском интерфейсе.
Журнал ошибок должен быть легко доступен на некоторой административной панели, чтобы кто-то мог просмотреть его в случае, если клиент сообщает о несоответствии между командами записи / чтения и чтения / запроса..
Это также работает, если у вас есть свои Readmodels, связанные друг с другом, то есть одному Readmodel нужны данные из другого канонического Readmodel.Хотя это кажется плохим, это не так, это всегда зависит.Бывают случаи, когда вы торгуете дублированием кода / логики программы обновления с упругостью.
Асинхронный, в другом процессе Средство чтения readmodel.Это используется, когда я использую полное разделение Readmodel от других Readmodels, когда сбой Readmodel не приведет к снижению всей стороны чтения;или когда Readmodel нужен другой язык, отличный от монолита.В основном это микросервис.Когда что-то плохое происходит внутри Readmodel, необходимо, чтобы какой-то авторитетный компонент более высокого уровня был уведомлен, то есть администратор был уведомлен по электронной почте, SMS или другим способом.
Модель чтения также должна иметь панель состояния со всеми видами метрик о событиях, которые она обработала, если есть пробелы, если есть ошибки или предупреждения;он также должен иметь командную панель, где администратор может перестроить ее в любое время, предпочтительно без простоев системы.
При любом подходе модели чтения должны легко перестраиваться.
КакВы бы выбрали между подходом тяги и подходом толчка?Если бы вы использовали очередь сообщений с push (событиями)
Я предпочитаю подход на основе извлечения, потому что:
- он не использует другой компонент с состоянием, такой как очередь сообщений,еще одна вещь, которой нужно управлять, которая потребляет ресурсы и которая может (а может и потерпит неудачу)
- , каждая Readmodel потребляет события со скоростью, которую он хочет
- , каждая Readmodel может легко изменить в любой момент, чтотипы событий, которые он потребляет
- , каждый Readmodel может быть легко в любое время перестроен, запрашивая все события с начала
- , там порядок событий точно такой же, как источник истины, потому что вы извлекаете изисточник правды
Бывают случаи, когда я выбираю очередь сообщений:
- , вам нужно, чтобы события были доступны, даже если хранилище событий не
- вам нужны конкурентные / параллельные потребители
- вы не хотите отслеживать, какие сообщения вы потребляете;по мере их использования они автоматически удаляются из очереди