public void Concurrent_read_only_access_to_aggregate_history_can_occur_in_paralell()
{
var user = new User();
user.Register("[email protected]", "password", Guid.NewGuid());
using (var session = OpenSession(CreateStore()))
{
session.Save(user);
}
var iterations = 20;
var delayEachTransactionByMilliseconds = 100;
Action readUserHistory = () =>
{
using(var session = OpenSession(CreateStore()))
{
using(var transaction = new TransactionScope())
{
((IEventStoreReader)session).GetHistory(user.Id);
Thread.Sleep(TimeSpanExtensions.Milliseconds(delayEachTransactionByMilliseconds));
transaction.Complete();
}
}
};
readUserHistory();//one warmup to get consistent times later.
var timeForSingleTransactionalRead = (int)StopwatchExtensions.TimeExecution(readUserHistory).TotalMilliseconds;
var timingsSummary = TimeAsserter.ExecuteThreaded(
readUserHistory,
iterations: iterations,
timeIndividualExecutions:true,
maxTotal: ((iterations * timeForSingleTransactionalRead) / 2).Milliseconds(),
description: $"If access is serialized the time will be approximately {iterations * timeForSingleTransactionalRead} milliseconds. If parelellized it should be far below this value.");
timingsSummary.Average.Should().BeLessThan(delayEachTransactionByMilliseconds.Milliseconds());
timingsSummary.IndividualExecutionTimes.Sum().Should().BeGreaterThan(timingsSummary.Total);
}