Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Using EnableRdi(false) attribute results in NullReferenceException from LogStateMachineCompletion
Magnus Lidbom
#1 Posted : Wednesday, November 20, 2024 10:14:11 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/30/2012(UTC)
Posts: 30

Thanks: 5 times
Was thanked: 4 time(s) in 4 post(s)
It seems to not be entirely deterministic. The first time I tried to use the attribute it happened as soon as I applied it.
Later, in other code, I thought it was working, but then when I restarted the NCrunch engine the test started failing with the below exception.
For yet another test it seems to just work so far.

Code:

EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object.
   at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.RdiEventListener.NCrunchLogStateMachineCompletion(Object stateMachineInstance, Int32 componentMappingId, UInt32 outerScopeTransientId, UInt32 outerScopeFrameIndex, Int64 frameStartInLog)
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.Run(SyncOrAsync syncOrAsync, Action synchronous, Func`1 asynchronous) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 39
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.Run(SyncOrAsync syncOrAsync, Action synchronous, Func`1 asynchronous)
   at Composable.Persistence.PgSql.IComposableNpgsqlConnection.ComposableNpgsqlConnection.Composable.Persistence.Common.AdoCE.IPoolableConnection.OpenAsyncFlex(SyncOrAsync syncOrAsync) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\PgSql\ComposableNpgsqlConnection.cs:line 24
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.SyncResult(Task this) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 52
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.<>c__DisplayClass1_0.<AsSync>b__0() in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 20
   at Composable.SystemCE.DiagnosticsCE.StopwatchCE.TimeExecution(Stopwatch this, Action action) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\DiagnosticsCE\StopwatchCE.cs:line 28
   at Composable.SystemCE.DiagnosticsCE.StopwatchCE.TimeExecution(Action action) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\DiagnosticsCE\StopwatchCE.cs:line 20
   at Composable.SystemCE.DiagnosticsCE.StopwatchCE.TimeExecutionFlexAsync(SyncOrAsync syncOrAsync, Func`2 syncOrAsyncAction) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\DiagnosticsCE\StopwatchCE.cs:line 63
   at Composable.SystemCE.DiagnosticsCE.TimingsStatisticsCollector.TimeAsyncFlex(SyncOrAsync syncOrAsync, Func`2 syncOrAsyncFunc) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\DiagnosticsCE\TimingsStatisticsCollector.cs:line 81
   at Composable.Persistence.Common.AdoCE.DbConnectionManager`2.DefaultDbConnectionManager.OpenConnectionAsyncFlex(SyncOrAsync syncOrAsync) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\DbConnectionPool.Pools.cs:line 61
   at Composable.Persistence.Common.AdoCE.DbConnectionManager`2.DefaultDbConnectionManager.UseConnectionAsyncFlex[TResult](SyncOrAsync syncOrAsync, Func`2 func) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\DbConnectionPool.Pools.cs:line 69
   at Composable.Persistence.Common.AdoCE.DbConnectionManager`2.TransactionAffinityDbConnectionManager.UseConnectionAsyncFlex[TResult](SyncOrAsync syncOrAsync, Func`2 func) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\DbConnectionPool.Pools.cs:line 87
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.SyncResult[TResult](Task`1 this) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 45
   at Composable.Persistence.Common.AdoCE.IDbConnectionPool`2.UseConnection[TResult](Func`2 func) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\IDbConnectionPool.cs:line 18
   at Composable.Persistence.Common.AdoCE.IDbConnectionPool`2.UseCommand[TResult](Func`2 action)
   at Composable.Persistence.PgSql.Testing.Databases.PgSqlDatabasePool.ResetDatabase(Database db) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\PgSql\Testing\Databases\PgSqlDatabasePool.cs:line 64
   at Composable.Testing.Databases.DatabasePool.<>c__DisplayClass12_1.<ConnectionStringFor>b__3() in C:\Dev\Composable\src\framework\Composable.CQRS\Testing\Databases\DatabasePool.cs:line 84
   at Composable.SystemCE.TransactionsCE.TransactionScopeCe.Execute(Action action, TransactionScopeOption option, IsolationLevel isolationLevel) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\TransactionsCE\TransactionScopeCE.cs:line 28
   at Composable.SystemCE.TransactionsCE.TransactionScopeCe.SuppressAmbient(Action action) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\TransactionsCE\TransactionScopeCE.cs:line 13
   at Composable.Testing.Databases.DatabasePool.<>c__DisplayClass12_0.<ConnectionStringFor>b__0() in C:\Dev\Composable\src\framework\Composable.CQRS\Testing\Databases\DatabasePool.cs:line 84

Remco
#2 Posted : Wednesday, November 20, 2024 11:20:10 PM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,135

Thanks: 959 times
Was thanked: 1290 time(s) in 1196 post(s)
Hi, thanks for sharing this issue.

My first thought here is whether this might be due to overlapping threads from other tests that have RDI enabled. Can you reproduce the issue at all by running the test in isolation?
Magnus Lidbom
#3 Posted : Wednesday, November 20, 2024 11:44:35 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/30/2012(UTC)
Posts: 30

Thanks: 5 times
Was thanked: 4 time(s) in 4 post(s)
Remco;17727 wrote:
My first thought here is whether this might be due to overlapping threads from other tests that have RDI enabled. Can you reproduce the issue at all by running the test in isolation?


That test no longer has the attribute. I need to get work done :)
But with the test that just started failing with the attribute applied, yes I can.
It crashes every time when I run just that test alone from the test runner. But on the topic of threads, this test does run multiple threads internally.
Here is the complete output from the test:


Code:

NCrunch: This test was executed on server '(local)'

INFO:Composable.Testing.Databases.DatabasePool: 00:39:45.621 Reserved pool database: Composable_DatabasePool_0003

############################################# ERROR in : Composable.Testing.Databases.DatabasePool #############################################
MESSAGE:  
EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object.
   at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.MemoryMappedLog.LogStateMachineCompletion(Object stateMachineInstance, Int32 componentMappingId, UInt32 outerScopeTransientId, UInt32 outerScopeFrameIndex, Int64 frameStartInLog)
   at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.RdiEventListener.NCrunchLogStateMachineCompletion(Object stateMachineInstance, Int32 componentMappingId, UInt32 outerScopeTransientId, UInt32 outerScopeFrameIndex, Int64 frameStartInLog)
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.Run(SyncOrAsync syncOrAsync, Action synchronous, Func`1 asynchronous) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 39
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.Run(SyncOrAsync syncOrAsync, Action synchronous, Func`1 asynchronous)
   at Composable.Persistence.MsSql.IComposableMsSqlConnection.ComposableMsSqlConnection.Composable.Persistence.Common.AdoCE.IPoolableConnection.OpenAsyncFlex(SyncOrAsync syncOrAsync) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\ComposableMsSqlConnection.cs:line 21
   at Composable.Persistence.Common.AdoCE.DbConnectionManager`2.DefaultDbConnectionManager.OpenConnectionAsyncFlex(SyncOrAsync syncOrAsync) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\DbConnectionPool.Pools.cs:line 53
   at Composable.Persistence.Common.AdoCE.DbConnectionManager`2.DefaultDbConnectionManager.UseConnectionAsyncFlex[TResult](SyncOrAsync syncOrAsync, Func`2 func) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\DbConnectionPool.Pools.cs:line 69
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.SyncResult[TResult](Task`1 this) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 45
   at Composable.Persistence.Common.AdoCE.IDbConnectionPool`2.UseConnection(Action`1 action) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\IDbConnectionPool.cs:line 21
   at Composable.Persistence.MsSql.Testing.Databases.MsSqlDatabasePool.ResetDatabase(Database db) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\Testing\Databases\MsSqlDatabasePool.cs:line 52
   at Composable.Testing.Databases.DatabasePool.<>c__DisplayClass12_1.<ConnectionStringFor>b__3() in C:\Dev\Composable\src\framework\Composable.CQRS\Testing\Databases\DatabasePool.cs:line 84
   at Composable.SystemCE.TransactionsCE.TransactionScopeCe.Execute(Action action, TransactionScopeOption option, IsolationLevel isolationLevel) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\TransactionsCE\TransactionScopeCE.cs:line 28
   at Composable.SystemCE.TransactionsCE.TransactionScopeCe.SuppressAmbient(Action action) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\TransactionsCE\TransactionScopeCE.cs:line 13
   at Composable.Testing.Databases.DatabasePool.<>c__DisplayClass12_0.<ConnectionStringFor>b__0() in C:\Dev\Composable\src\framework\Composable.CQRS\Testing\Databases\DatabasePool.cs:line 84


############################################# SERIALIZED EXCEPTION #############################################
{
  "$type": "System.NullReferenceException, System.Private.CoreLib",
  "Message": "Object reference not set to an instance of an object.",
  "Data": {
    "$type": "System.Collections.ListDictionaryInternal, System.Private.CoreLib"
  },
  "InnerException": null,
  "HelpLink": null,
  "Source": "nCrunch.TestRuntime.DotNetCore",
  "HResult": -2147467261
}

############################################# END ERROR #############################################

System.NullReferenceException : Object reference not set to an instance of an object.
   at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.MemoryMappedLog.LogStateMachineCompletion(Object stateMachineInstance, Int32 componentMappingId, UInt32 outerScopeTransientId, UInt32 outerScopeFrameIndex, Int64 frameStartInLog)
   at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.RdiEventListener.NCrunchLogStateMachineCompletion(Object stateMachineInstance, Int32 componentMappingId, UInt32 outerScopeTransientId, UInt32 outerScopeFrameIndex, Int64 frameStartInLog)
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.Run(SyncOrAsync syncOrAsync, Action synchronous, Func`1 asynchronous) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 39
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.Run(SyncOrAsync syncOrAsync, Action synchronous, Func`1 asynchronous)
   at Composable.Persistence.MsSql.IComposableMsSqlConnection.ComposableMsSqlConnection.Composable.Persistence.Common.AdoCE.IPoolableConnection.OpenAsyncFlex(SyncOrAsync syncOrAsync) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\ComposableMsSqlConnection.cs:line 21
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.SyncResult(Task this) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 52
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.<>c__DisplayClass1_0.<AsSync>b__0() in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 20
   at Composable.SystemCE.DiagnosticsCE.StopwatchCE.TimeExecution(Stopwatch this, Action action) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\DiagnosticsCE\StopwatchCE.cs:line 28
   at Composable.SystemCE.DiagnosticsCE.StopwatchCE.TimeExecution(Action action) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\DiagnosticsCE\StopwatchCE.cs:line 20
   at Composable.SystemCE.DiagnosticsCE.StopwatchCE.TimeExecutionFlexAsync(SyncOrAsync syncOrAsync, Func`2 syncOrAsyncAction) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\DiagnosticsCE\StopwatchCE.cs:line 63
   at Composable.SystemCE.DiagnosticsCE.TimingsStatisticsCollector.TimeAsyncFlex(SyncOrAsync syncOrAsync, Func`2 syncOrAsyncFunc) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\DiagnosticsCE\TimingsStatisticsCollector.cs:line 81
   at Composable.Persistence.Common.AdoCE.DbConnectionManager`2.DefaultDbConnectionManager.OpenConnectionAsyncFlex(SyncOrAsync syncOrAsync) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\DbConnectionPool.Pools.cs:line 61
   at Composable.Persistence.Common.AdoCE.DbConnectionManager`2.DefaultDbConnectionManager.UseConnectionAsyncFlex[TResult](SyncOrAsync syncOrAsync, Func`2 func) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\DbConnectionPool.Pools.cs:line 69
   at Composable.SystemCE.ThreadingCE.SyncOrAsyncCE.SyncResult[TResult](Task`1 this) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\SyncOrAsync.cs:line 45
   at Composable.Persistence.Common.AdoCE.IDbConnectionPool`2.UseConnection[TResult](Func`2 func) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\IDbConnectionPool.cs:line 18
   at Composable.Persistence.Common.AdoCE.IDbConnectionPool`2.ExecuteScalar(String commandText) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\Common\AdoCE\IDbConnectionPool.cs:line 35
   at Composable.Persistence.MsSql.Testing.Databases.MsSqlDatabasePool.EnsureDatabaseExistsAndIsEmpty(Database db) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\Testing\Databases\MsSqlDatabasePool.cs:line 30
   at Composable.Testing.Databases.DatabasePool.<>c__DisplayClass12_0.<ConnectionStringFor>b__0() in C:\Dev\Composable\src\framework\Composable.CQRS\Testing\Databases\DatabasePool.cs:line 89
   at Composable.SystemCE.ThreadingCE.ResourceAccess.MonitorCE.Update[T](Func`1 func) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\ResourceAccess\MonitorCE.Functional..cs:line 22
   at Composable.Testing.Databases.DatabasePool.ConnectionStringFor(String reservationName) in C:\Dev\Composable\src\framework\Composable.CQRS\Testing\Databases\DatabasePool.cs:line 47
   at Composable.Persistence.MsSql.DependencyInjection.MsSqlPersistenceLayerRegistrar.<>c__DisplayClass1_1.<RegisterMsSqlPersistenceLayer>b__8() in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\DependencyInjection\MsSqlPersistenceLayerRegistrar.cs:line 33
   at Composable.Persistence.MsSql.SystemExtensions.IMsSqlConnectionPool.MsSqlConnectionPool.<>c__DisplayClass3_0.<.ctor>b__0() in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\SystemExtensions\MsSqlConnectionPool.cs:line 25
   at Composable.SystemCE.OptimizedLazy`1.<get_Value>b__4_0() in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\OptimizedLazy.cs:line 18
   at Composable.SystemCE.ThreadingCE.ResourceAccess.MonitorCE.Update[T](Func`1 func) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\ThreadingCE\ResourceAccess\MonitorCE.Functional..cs:line 22
   at Composable.SystemCE.OptimizedLazy`1.get_Value() in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\OptimizedLazy.cs:line 18
   at Composable.Persistence.MsSql.SystemExtensions.IMsSqlConnectionPool.MsSqlConnectionPool.get_Pool() in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\SystemExtensions\MsSqlConnectionPool.cs:line 18
   at Composable.Persistence.MsSql.SystemExtensions.IMsSqlConnectionPool.MsSqlConnectionPool.UseConnectionAsyncFlex[TResult](SyncOrAsync syncOrAsync, Func`2 func) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\SystemExtensions\MsSqlConnectionPool.cs:line 33
   at Composable.Persistence.Common.AdoCE.IDbConnectionPool`2.UseConnection[TResult](Func`2 func)
   at Composable.Persistence.Common.AdoCE.IDbConnectionPool`2.UseCommand[TResult](Func`2 action)
   at Composable.Persistence.MsSql.EventStore.MsSqlEventStoreConnectionManager.UseCommand[TResult](Boolean suppressTransactionWarning, Func`2 action) in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\EventStore\MsSqlEventStoreConnectionManager.cs:line 31
   at Composable.Persistence.MsSql.EventStore.MsSqlEventStorePersistenceLayer.<SetupSchemaIfDatabaseUnInitialized>b__10_0() in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\EventStore\MsSqlEventStorePersistenceLayer.Schema.cs:line 17
   at Composable.SystemCE.TransactionsCE.TransactionScopeCe.Execute(Action action, TransactionScopeOption option, IsolationLevel isolationLevel) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\TransactionsCE\TransactionScopeCE.cs:line 28
   at Composable.SystemCE.TransactionsCE.TransactionScopeCe.SuppressAmbient(Action action) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\TransactionsCE\TransactionScopeCE.cs:line 13
   at Composable.Persistence.MsSql.EventStore.MsSqlEventStorePersistenceLayer.SetupSchemaIfDatabaseUnInitialized() in C:\Dev\Composable\src\framework\Composable.CQRS.ExternalDependencies\Persistence\MsSql\EventStore\MsSqlEventStorePersistenceLayer.Schema.cs:line 13
   at Composable.Persistence.EventStore.EventStore.SaveSingleAggregateEvents(IReadOnlyList`1 aggregateEvents) in C:\Dev\Composable\src\framework\Composable.CQRS\Persistence\EventStore\EventStore.cs:line 140
   at Composable.Persistence.EventStore.EventStoreUpdater.<>c__DisplayClass16_0`1.<Save>b__0(IReadOnlyList`1 events) in C:\Dev\Composable\src\framework\Composable.CQRS\Persistence\EventStore\EventStoreUpdater.cs:line 98
   at Composable.Persistence.EventStore.Aggregates.Aggregate`5.Commit(Action`1 commitEvents) in C:\Dev\Composable\src\framework\Composable.CQRS\Persistence\EventStore\Aggregates\Aggregate..cs:line 120
   at Composable.Persistence.EventStore.EventStoreUpdater.Save[TAggregate](TAggregate aggregate) in C:\Dev\Composable\src\framework\Composable.CQRS\Persistence\EventStore\EventStoreUpdater.cs:line 87
   at Composable.Tests.CQRS.EventStoreUpdaterTest.<>c__DisplayClass24_0.<Concurrent_read_only_access_to_aggregate_history_can_occur_in_parallel>b__0(IEventStoreUpdater session) in C:\Dev\Composable\src\framework\Composable.CQRS.Tests\CQRS\EventStoreUpdaterTest.cs:line 434
   at Composable.Tests.CQRS.EventStoreUpdaterTest.<>c__DisplayClass5_0.<UseInTransactionalScope>b__0() in C:\Dev\Composable\src\framework\Composable.CQRS.Tests\CQRS\EventStoreUpdaterTest.cs:line 80
   at Composable.SystemCE.TransactionsCE.TransactionScopeCe.Execute(Action action, TransactionScopeOption option, IsolationLevel isolationLevel) in C:\Dev\Composable\src\framework\Composable.CQRS\SystemCE\TransactionsCE\TransactionScopeCE.cs:line 28
   at Composable.DependencyInjection.ServiceLocatorTransactionRunner.ExecuteTransactionInIsolatedScope(IServiceLocator me, Action action) in C:\Dev\Composable\src\framework\Composable.CQRS\DependencyInjection\TransactionalExtensions.cs:line 24
   at Composable.Tests.CQRS.EventStoreUpdaterTest.UseInTransactionalScope(Action`1 useSession) in C:\Dev\Composable\src\framework\Composable.CQRS.Tests\CQRS\EventStoreUpdaterTest.cs:line 79
   at Composable.Tests.CQRS.EventStoreUpdaterTest.Concurrent_read_only_access_to_aggregate_history_can_occur_in_parallel() in C:\Dev\Composable\src\framework\Composable.CQRS.Tests\CQRS\EventStoreUpdaterTest.cs:line 434
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)


Remco
#4 Posted : Thursday, November 21, 2024 12:07:04 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,135

Thanks: 959 times
Was thanked: 1290 time(s) in 1196 post(s)
Thanks for these extra details. My current theory is that there is a thread running past the end of the main test execution and that it's getting into trouble with RDI collection while the async block winds down.

Does the test contain any mechanisms to make sure that the threads have all completed their execution before it completes?
Magnus Lidbom
#5 Posted : Thursday, November 21, 2024 12:13:20 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/30/2012(UTC)
Posts: 30

Thanks: 5 times
Was thanked: 4 time(s) in 4 post(s)
Remco;17732 wrote:
Does the test contain any mechanisms to make sure that the threads have all completed their execution before it completes?

It does. But more importantly, this exception is thrown at the beginning of the test not during teardown:


Code:

   [Test, EnableRdi(false)]
   public void Concurrent_read_only_access_to_aggregate_history_can_occur_in_parallel()
   {
      var user = new User();
      user.Register("email@email.se", "password", Guid.NewGuid());

      UseInTransactionalScope(session => session.Save(user)); // ==== Exception is thrown here ====


      var threadedIterations = 20;
      var delayEachTransactionBy = 1.Milliseconds();

      void ReadUserHistory()
      {
         UseInTransactionalScope(session =>
         {
            ((IEventStoreReader)session).GetHistory(user.Id);
            Thread.Sleep(delayEachTransactionBy);
         });
      }


      var singleThreadedExecutionTime = StopwatchCE.TimeExecution(ReadUserHistory, iterations: threadedIterations).Total;

      var timingsSummary = TimeAsserter.ExecuteThreaded(
         action: ReadUserHistory,
         iterations: threadedIterations,
         maxTotal: singleThreadedExecutionTime / 2,
         maxDegreeOfParallelism: 5,
         description: $"If access is serialized the time will be approximately {singleThreadedExecutionTime} milliseconds. If parallelized it should be far below this value.");

      timingsSummary.IndividualExecutionTimes.Sum().Should().BeGreaterThan(timingsSummary.Total, "If the sum elapsed time of the parts that run in parallel is not greater than the clock time passed parallelism is not taking place.");
   }
Remco
#6 Posted : Thursday, November 21, 2024 12:42:03 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,135

Thanks: 959 times
Was thanked: 1290 time(s) in 1196 post(s)
Thanks, I think I've isolated this issue. Would you be interested in trying out a new build with a fix included?
1 user thanked Remco for this useful post.
Magnus Lidbom on 11/21/2024(UTC)
Magnus Lidbom
#7 Posted : Thursday, November 21, 2024 1:00:17 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/30/2012(UTC)
Posts: 30

Thanks: 5 times
Was thanked: 4 time(s) in 4 post(s)
Remco;17735 wrote:
Thanks, I think I've isolated this issue. Would you be interested in trying out a new build with a fix included?

Very much interested :)
Remco
#8 Posted : Thursday, November 21, 2024 1:04:48 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,135

Thanks: 959 times
Was thanked: 1290 time(s) in 1196 post(s)
Magnus Lidbom;17736 wrote:

Very much interested :)


Excellent. I'm nursing one through our build system at the moment and will let you know when it's available.
Remco
#9 Posted : Thursday, November 21, 2024 4:29:01 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,135

Thanks: 959 times
Was thanked: 1290 time(s) in 1196 post(s)
1 user thanked Remco for this useful post.
Magnus Lidbom on 11/21/2024(UTC)
Magnus Lidbom
#10 Posted : Thursday, November 21, 2024 5:03:10 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/30/2012(UTC)
Posts: 30

Thanks: 5 times
Was thanked: 4 time(s) in 4 post(s)
Remco;17744 wrote:
Ok, the new build is ready! I'm keen to hear if this solve the problem for you.


Problem SOLVED :D
* No more NullReferenceException
* Only 7 performance tests fail now
* They fail with a loss in performance of only something like 40-60%
Heroic effort getting a fix out this fast. Thank you!

One last question Can I detect at runtime if RDI is enabled somehow? And the same question for instrumentation.
I don't mind if it is ugly and hacky as long as it works. It's just going to be used for automatically adjusting performance test expectations depending on the environment in which the test is running.
Remco
#11 Posted : Thursday, November 21, 2024 6:02:44 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,135

Thanks: 959 times
Was thanked: 1290 time(s) in 1196 post(s)
Magnus Lidbom;17745 wrote:

Problem SOLVED :D


Awesome :)

Magnus Lidbom;17745 wrote:

One last question Can I detect at runtime if RDI is enabled somehow? And the same question for instrumentation.
I don't mind if it is ugly and hacky as long as it works. It's just going to be used for automatically adjusting performance test expectations depending on the environment in which the test is running.


There isn't a way you can do this directly, but you might be able to find another way.

For example, you could detect if the test is running on your grid node by checking for an environment variable that is specific to the node.

It may also be worth reframing the question. Instead of detecting RDI, perhaps you could analyse the base speed of the machine running the test. At the start of the test, make a call to a small method that runs a tight loop for a few thousand iterations. Measure the performance, then use this measurement to adjust the tolerance of your performance test. In this way, the test is also made to be more resilient when the machine is under heavy load or is running on slow hardware.
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

YAF | YAF © 2003-2011, Yet Another Forum.NET
This page was generated in 0.085 seconds.
Trial NCrunch
Take NCrunch for a spin
Do your fingers a favour and supercharge your testing workflow
Free Download