When creating a sagapersister I have to implement ISagaStorage
which defines:
Task<ISagaData> Find(Type sagaDataType, string propertyName, object propertyValue);
Task Insert(ISagaData sagaData, IEnumerable<ISagaCorrelationProperty> correlationProperties);
Task Update(ISagaData sagaData, IEnumerable<ISagaCorrelationProperty> correlationProperties);
Task Delete(ISagaData sagaData);
When implementing insert the ISagaData.Id
can be used for handling concurrent inserts (if this is a case). When implementing update the ISagaData.Revision
can be used for handling concurrent updates on the same saga.
After writing some tests with highly concurrent configuration(both workers and parallellism) I can se that multiple sagas are created when I would expect only one to be created. This is probably beacause the following flow executes concurrent for multiple incoming messages without any "readlock":
I have read through different implementations of ISagaStore
(MongoDb, RavenDb) but havent been able to find any mechanism which prevents creation of multiple "identical" sagas caused by concurrent handling of incoming messages.
Long story short: Is there any mechanism or pattern in Rebus that could be used to prevent creation of multiple "identical" sagas caused by concurrent handling of messages?
One possible solution is to to check for identical correlation properties/values on insert?
(or maybe my understanding of the whole concept is wrong - In that case I would appreciate any help understanding this)
Is there any mechanism or pattern in Rebus that could be used to prevent creation of multiple "identical" sagas caused by concurrent handling of messages?
Yes!
A saga persister – at least one that adheres to Rebus' contract tests – should enforce uniqueness of all correlation properties.
This would cause concurrent insert operations to result in rollbacks for all but the first.