What is causing EventStore to throw ConcurrencyExc

2019-04-10 17:59发布

问题:

Using JOliver EventStore 3.0, and just getting started with simple samples.

I have a simple pub/sub CQRS implementation using NServiceBus. A client sends commands on the bus, a domain server recieves and processes the commands and stores events to the eventstore, which are then published on the bus by the eventstore's dispatcher. a read-model server then subscribes to those events to update the read-model. Nothing fancy, pretty much by-the-book.

It is working, but just in simple tests I am getting lots of concurrency exceptions (intermittantly) on the domain server when the event is stored to the EventStore. It properly retries, but sometimes it hits the 5 retry limit and the command ends up on the error queue.

Where could I start investigating to see what is causing the concurrency exception? I remove the dispatcher and just focus on storing events and it has the same issue.

I'm using RavenDB for persistence of my EventStore. I'm not doing anything fancy, just this:

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

The stack trace for the exception looks like this:

2012-03-17 18:34:01,166 [Worker.14] WARN NServiceBus.Unicast.UnicastBus [(null)] <(null)> - EmployeeCommandHandler failed handling message. EventStore.ConcurrencyException: Exception of type 'EventStore.ConcurrencyException' was thrown. at EventStore.OptimisticPipelineHook.PreCommit(Commit attempt) in c:\Code\public\EventStore\src\proj\EventStore.Core\OptimisticPipelineHook.cs:line 55 at EventStore.OptimisticEventStore.Commit(Commit attempt) in c:\Code\public\EventStore\src\proj\EventStore.Core\OptimisticEventStore.cs:line 90 at EventStore.OptimisticEventStream.PersistChanges(Guid commitId) in c:\Code\public\EventStore\src\proj\EventStore.Core\OptimisticEventStream.cs:line 168 at EventStore.OptimisticEventStream.CommitChanges(Guid commitId) in c:\Code\public\EventStore\src\proj\EventStore.Core\OptimisticEventStream.cs:line 149 at CQRSTest3.Domain.Extensions.StoreEvent(IStoreEvents eventStore, Guid entityId, Object evt) in C:\dev\test\CQRSTest3\CQRSTest3.Domain\Extensions.cs:line 13 at CQRSTest3.Domain.ComandHandlers.EmployeeCommandHandler.Handle(ChangeEmployeeSalary message) in C:\dev\test\CQRSTest3\CQRSTest3.Domain\ComandHandlers\Emplo yeeCommandHandler.cs:line 55

回答1:

I figured it out. Had to dig through source code to find it though. I wish this was better documented! Here's my new eventstore wireup:

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

I had to add .ConsistentQueries() in order for the raven persistence provider to internally use WaitForNonStaleResults on the queries eventstore was making to raven.

Basically when I add a new event, and then try to add another before raven has caught up with indexing, the stream revision was not up to date. The second event would step on the first one.