@@ -936,10 +936,31 @@ async Task ExpectException(Task t)
936936 Assert . True ( await ctx . CallEntityAsync < bool > ( entityId , "exists" ) ) ;
937937 }
938938
939- // send batch
940- ctx . SignalEntity ( entityId , "Set" , 42 ) ;
941- ctx . SignalEntity ( entityId , "SetThenThrow" , 333 ) ;
942- ctx . SignalEntity ( entityId , "DeleteThenThrow" ) ;
939+ // we use this utility function to try to enforce that a bunch of signals is delivered as a single batch.
940+ // This is required for some of the tests here to work, since the batching affects the entity state management.
941+ // The "enforcement" mechanism we use is not 100% failsafe (it still makes timing assumptions about the provider)
942+ // but it should be more reliable than the original version of this test which failed quite frequently, as it was
943+ // simply assuming that signals that are sent at the same time are always processed as a batch.
944+ async Task ProcessAllSignalsInSingleBatch ( Action sendSignals )
945+ {
946+ // first issue a signal that, when delivered, keeps the entity busy for a second
947+ ctx . SignalEntity ( entityId , "delay" , 1 ) ;
948+
949+ // we now need to yield briefly so that the delay signal is sent before the others
950+ await ctx . CreateTimer ( ctx . CurrentUtcDateTime + TimeSpan . FromMilliseconds ( 1 ) , CancellationToken . None ) ;
951+
952+ // now send the signals in the batch. These should all arrive and get queued (inside the storage provider)
953+ // while the entity is executing the delay operation. Therefore, after the delay operation finishes,
954+ // all of the signals are processed in a single batch.
955+ sendSignals ( ) ;
956+ }
957+
958+ await ProcessAllSignalsInSingleBatch ( ( ) =>
959+ {
960+ ctx . SignalEntity ( entityId , "Set" , 42 ) ;
961+ ctx . SignalEntity ( entityId , "SetThenThrow" , 333 ) ;
962+ ctx . SignalEntity ( entityId , "DeleteThenThrow" ) ;
963+ } ) ;
943964
944965 if ( rollbackOnException )
945966 {
@@ -951,12 +972,14 @@ async Task ExpectException(Task t)
951972 ctx . SignalEntity ( entityId , "Set" , 42 ) ;
952973 }
953974
954- // send batch
955- ctx . SignalEntity ( entityId , "Get" ) ;
956- ctx . SignalEntity ( entityId , "Set" , 42 ) ;
957- ctx . SignalEntity ( entityId , "Delete" ) ;
958- ctx . SignalEntity ( entityId , "Set" , 43 ) ;
959- ctx . SignalEntity ( entityId , "DeleteThenThrow" ) ;
975+ await ProcessAllSignalsInSingleBatch ( ( ) =>
976+ {
977+ ctx . SignalEntity ( entityId , "Get" ) ;
978+ ctx . SignalEntity ( entityId , "Set" , 42 ) ;
979+ ctx . SignalEntity ( entityId , "Delete" ) ;
980+ ctx . SignalEntity ( entityId , "Set" , 43 ) ;
981+ ctx . SignalEntity ( entityId , "DeleteThenThrow" ) ;
982+ } ) ;
960983
961984 if ( rollbackOnException )
962985 {
@@ -967,9 +990,11 @@ async Task ExpectException(Task t)
967990 Assert . False ( await ctx . CallEntityAsync < bool > ( entityId , "exists" ) ) ;
968991 }
969992
970- // send batch
971- ctx . SignalEntity ( entityId , "Set" , 55 ) ;
972- ctx . SignalEntity ( entityId , "SetToUnserializable" ) ;
993+ await ProcessAllSignalsInSingleBatch ( ( ) =>
994+ {
995+ ctx . SignalEntity ( entityId , "Set" , 55 ) ;
996+ ctx . SignalEntity ( entityId , "SetToUnserializable" ) ;
997+ } ) ;
973998
974999 if ( rollbackOnException )
9751000 {
@@ -981,11 +1006,13 @@ async Task ExpectException(Task t)
9811006 await ctx . CallEntityAsync < bool > ( entityId , "deletewithoutreading" ) ;
9821007 }
9831008
984- // send batch
985- ctx . SignalEntity ( entityId , "Set" , 56 ) ;
986- ctx . SignalEntity ( entityId , "SetToUnDeserializable" ) ;
987- ctx . SignalEntity ( entityId , "Set" , 12 ) ;
988- ctx . SignalEntity ( entityId , "SetThenThrow" , 999 ) ;
1009+ await ProcessAllSignalsInSingleBatch ( ( ) =>
1010+ {
1011+ ctx . SignalEntity ( entityId , "Set" , 56 ) ;
1012+ ctx . SignalEntity ( entityId , "SetToUnDeserializable" ) ;
1013+ ctx . SignalEntity ( entityId , "Set" , 12 ) ;
1014+ ctx . SignalEntity ( entityId , "SetThenThrow" , 999 ) ;
1015+ } ) ;
9891016
9901017 if ( rollbackOnException )
9911018 {
@@ -999,11 +1026,14 @@ async Task ExpectException(Task t)
9991026
10001027 await ctx . CallEntityAsync < bool > ( entityId , "deletewithoutreading" ) ;
10011028
1002- ctx . SignalEntity ( entityId , "Set" , 1 ) ;
1003- ctx . SignalEntity ( entityId , "Delete" ) ;
1004- ctx . SignalEntity ( entityId , "Set" , 2 ) ;
1005- ctx . SignalEntity ( entityId , "Delete" ) ;
1006- ctx . SignalEntity ( entityId , "SetThenThrow" , 3 ) ;
1029+ await ProcessAllSignalsInSingleBatch ( ( ) =>
1030+ {
1031+ ctx . SignalEntity ( entityId , "Set" , 1 ) ;
1032+ ctx . SignalEntity ( entityId , "Delete" ) ;
1033+ ctx . SignalEntity ( entityId , "Set" , 2 ) ;
1034+ ctx . SignalEntity ( entityId , "Delete" ) ;
1035+ ctx . SignalEntity ( entityId , "SetThenThrow" , 3 ) ;
1036+ } ) ;
10071037
10081038 if ( rollbackOnException )
10091039 {
0 commit comments