Что заставляет EventStore так легко вызывать ConcurrencyException?

Использование JOliver EventStore 3.0 и начало работы с простыми примерами.

У меня есть простая реализация pub/sub CQRS с использованием NServiceBus. Клиент отправляет команды по шине, сервер домена получает и обрабатывает команды и сохраняет события в хранилище событий, которые затем публикуются на шине диспетчером хранилища событий. затем сервер модели чтения подписывается на эти события, чтобы обновить модель чтения. Ничего особенного, все по-книжному.

Это работает, но только в простых тестах я получаю много исключений параллелизма (периодически) на сервере домена, когда событие сохраняется в EventStore. Он правильно повторяет попытку, но иногда он достигает предела 5 повторных попыток, и команда попадает в очередь ошибок.

Где я могу начать расследование, чтобы узнать, что вызывает исключение параллелизма? Я удаляю диспетчер и просто сосредотачиваюсь на хранении событий, и у него та же проблема.

Я использую RavenDB для сохранения моего EventStore. Я не делаю ничего необычного, просто это:

using (var stream = eventStore.OpenStream(entityId, 0, int.MaxValue))
{
  stream.Add(new EventMessage { Body = myEvent });
  stream.CommitChanges(Guid.NewGuid());
}

Трассировка стека для исключения выглядит так:

17.03.2012 18:34:01,166 [Worker.14] WARN NServiceBus.Unicast.UnicastBus [(null)] ‹(null)> — Ошибка обработки сообщения EmployeeCommandHandler. EventStore.ConcurrencyException: возникло исключение типа EventStore.ConcurrencyException. в EventStore.OptimisticPipelineHook.PreCommit(попытка фиксации) в c:\Code\public\EventStore\src\proj\EventStore.Core\OptimisticPipelineHook.cs:строка 55 в EventStore.OptimisticEventStore.Commit(попытка фиксации) в c:\Code\ public\EventStore\src\proj\EventStore.Core\OptimisticEventStore.cs:строка 90 в EventStore.OptimisticEventStream.PersistChanges(Guid commitId) в c:\Code\public\EventStore\src\proj\EventStore.Core\OptimisticEventStream.cs: строка 168 в EventStore.OptimisticEventStream.CommitChanges(Guid commitId) в c:\Code\public\EventStore\src\proj\EventStore.Core\OptimisticEventStream.cs: строка 149 в CQRSTest3.Domain.Extensions.StoreEvent(IStoreEvents eventStore, Guid entityId , Object evt) в C:\dev\test\CQRSTest3\CQRSTest3.Domain\Extensions.cs:строка 13 в CQRSTest3.Domain.ComandHandlers.EmployeeCommandHandler.Handle(сообщение ChangeEmployeeSalary) в C:\dev\test\CQRSTest3\CQRSTest3. Домен\ComandHandlers\Emplo yeeCommandHandler.cs:строка 55


person Matt Johnson-Pint    schedule 18.03.2012    source источник
comment
Повторите свои тесты, используя, например. хранилище sql, чтобы узнать, связана ли проблема параллелизма с интеграцией RavenDb?   -  person Yves Reynhout    schedule 18.03.2012


Ответы (1)


Я понял. Пришлось копаться в исходном коде, чтобы найти его. Я бы хотел, чтобы это было лучше задокументировано! Вот моя новая разводка магазина событий:

EventStore = Wireup.Init()
          .UsingRavenPersistence("RavenDB")
          .ConsistentQueries()
          .InitializeStorageEngine()
          .Build();

Мне пришлось добавить .ConsistentQueries(), чтобы поставщик постоянства Raven мог внутренне использовать WaitForNonStaleResults для запросов, которые хранилище событий отправляло Raven.

В основном, когда я добавляю новое событие, а затем пытаюсь добавить другое до того, как Raven догнал индексацию, версия потока не была обновлена. Второе событие наступит на первое.

person Matt Johnson-Pint    schedule 19.03.2012
comment
Дополнительные баллы за нахождение этого. Одним из следующих шагов в EventStore является улучшение документов. - person Jonathan Oliver; 20.03.2012
comment
Рад видеть, что метод был доступен по крайней мере. Как только я понял, что это связано с устаревшими результатами запроса, я испугался, что мне придется взломать источник хранилища событий. Жду новых документов. :) - person Matt Johnson-Pint; 20.03.2012
comment
@JonathanOliver Я не использовал магазин событий и недавно наткнулся на это. Тогда я был новичком в Raven, но сейчас я гораздо больше погружен в него. Вы должны изменить .ConsitentQueries() реализацию. .WaitForNonStaleResults() действительно плох в производстве. Вы будете ждать вечно в загруженной системе. Вероятно, вам следует использовать .WaitForNonStaleResultsAsOfNow(), чтобы обеспечить отсечку. - person Matt Johnson-Pint; 24.12.2012
comment
@MattJohnson Я полагаю, было бы даже лучше использовать .WaitForNonStaleResultsAsOfLastWrite(), что не заставляет нас ждать других клиентов. Подробнее об этом здесь: ayende.com/blog/22529/enhancing-the -ravendb-consistency-model - person mbp; 15.08.2013