At the moment, no matter what the actual technology provider, IDataStore implementations are open to concurrency issues when we call any of these methods in SnapshottingDddCommandStore<TAggregateOrEntity>;
DeleteAsync()
ResurrectDeletedAsync() or
UpsertAsync()
We first fetch the record via IDataStore.RetrieveAsync() and then either:
RemoveAsync()
AddAsync() or,
ReplaceAsync()
The same problem exists with SnapshottingStore<TDto> implementations.
The same problem would exist in IBlobStore implementations.
We have the same kind of problem in a slightly different way for IEventStore in EventSourcingDddCommandStore<TAggregateRoot> between calling LoadAsync() and SaveAsync() if using a database implementation.
If we are doing this in a multi-threaded environment, which we are with HTTP requests, then there is an outside chance that in a busy SaaS system, we will experience concurrency issues, particularly more frequently with events sourced aggregates, using EventSourcingDddCommandStore<TAggregateRoot>
Solution
We can support a notion of a logical transaction, where the *Store classes above, create a transaction and pass that transaction to successive calls in the *Store methods, but also allow the developer to create and pass down transactions from their code into the *Store implementations.
Problem
At the moment, no matter what the actual technology provider,
IDataStore
implementations are open to concurrency issues when we call any of these methods inSnapshottingDddCommandStore<TAggregateOrEntity>
;DeleteAsync()
ResurrectDeletedAsync()
orUpsertAsync()
We first fetch the record viaIDataStore.RetrieveAsync()
and then either:RemoveAsync()
AddAsync()
or,ReplaceAsync()
The same problem exists with
SnapshottingStore<TDto>
implementations.The same problem would exist in
IBlobStore
implementations.We have the same kind of problem in a slightly different way for
IEventStore
inEventSourcingDddCommandStore<TAggregateRoot>
between callingLoadAsync()
andSaveAsync()
if using a database implementation.If we are doing this in a multi-threaded environment, which we are with HTTP requests, then there is an outside chance that in a busy SaaS system, we will experience concurrency issues, particularly more frequently with events sourced aggregates, using
EventSourcingDddCommandStore<TAggregateRoot>
Solution
We can support a notion of a logical transaction, where the
*Store
classes above, create a transaction and pass that transaction to successive calls in the*Store
methods, but also allow the developer to create and pass down transactions from their code into the*Store
implementations.