@@ -6399,6 +6399,112 @@ await ExecuteWorkerAsync<InstanceVisibleWorkflow>(async worker =>
6399
6399
} ) ;
6400
6400
}
6401
6401
6402
+ [ Workflow ]
6403
+ public class SignalsSameTaskWorkflow
6404
+ {
6405
+ private readonly List < string > signals = new ( ) ;
6406
+
6407
+ [ WorkflowRun ]
6408
+ public async Task < List < string > > RunAsync ( )
6409
+ {
6410
+ await Workflow . WaitConditionAsync ( ( ) => signals . Count > 0 ) ;
6411
+ return signals ;
6412
+ }
6413
+
6414
+ [ WorkflowSignal ]
6415
+ public async Task SignalAsync ( string value ) => signals . Add ( value ) ;
6416
+ }
6417
+
6418
+ [ Fact ]
6419
+ public async Task ExecuteWorkflowAsync_SignalsSameTask_ExecuteBeforeMain ( )
6420
+ {
6421
+ // Start the workflow with no worker
6422
+ var taskQueue = $ "tq-{ Guid . NewGuid ( ) } ";
6423
+ var handle = await Client . StartWorkflowAsync (
6424
+ ( SignalsSameTaskWorkflow wf ) => wf . RunAsync ( ) ,
6425
+ new ( id : $ "workflow-{ Guid . NewGuid ( ) } ", taskQueue ) ) ;
6426
+ // Send two signals
6427
+ await handle . SignalAsync ( wf => wf . SignalAsync ( "one" ) ) ;
6428
+ await handle . SignalAsync ( wf => wf . SignalAsync ( "two" ) ) ;
6429
+ // Now start the worker and wait for result
6430
+ await ExecuteWorkerAsync < SignalsSameTaskWorkflow > (
6431
+ async worker =>
6432
+ {
6433
+ // Confirm both signals were seen
6434
+ Assert . Equal ( new List < string > { "one" , "two" } , await handle . GetResultAsync ( ) ) ;
6435
+ // Confirm this completed in one task
6436
+ var history = await handle . FetchHistoryAsync ( ) ;
6437
+ Assert . Equal ( 1 , history . Events . Count ( e => e . WorkflowTaskCompletedEventAttributes != null ) ) ;
6438
+ } ,
6439
+ new ( taskQueue ) ) ;
6440
+ }
6441
+
6442
+ public class UnhandledCommandActivities
6443
+ {
6444
+ private readonly Func < Task > callOnActivity ;
6445
+ private bool called ;
6446
+
6447
+ public UnhandledCommandActivities ( Func < Task > callOnActivity ) => this . callOnActivity = callOnActivity ;
6448
+
6449
+ [ Activity ]
6450
+ public async Task WaitOnCallbackAsync ( )
6451
+ {
6452
+ // Only call if not called
6453
+ if ( ! called )
6454
+ {
6455
+ called = true ;
6456
+ await callOnActivity ( ) ;
6457
+ }
6458
+ }
6459
+ }
6460
+
6461
+ [ Workflow ]
6462
+ public class UnhandledCommandWorkflow
6463
+ {
6464
+ private readonly List < string > signals = new ( ) ;
6465
+
6466
+ [ WorkflowRun ]
6467
+ public async Task < List < string > > RunAsync ( )
6468
+ {
6469
+ await Workflow . ExecuteLocalActivityAsync (
6470
+ ( UnhandledCommandActivities acts ) => acts . WaitOnCallbackAsync ( ) ,
6471
+ new ( ) { StartToCloseTimeout = TimeSpan . FromMinutes ( 5 ) } ) ;
6472
+ return signals ;
6473
+ }
6474
+
6475
+ [ WorkflowSignal ]
6476
+ public async Task SignalAsync ( string value ) => signals . Add ( value ) ;
6477
+ }
6478
+
6479
+ [ Fact ]
6480
+ public async Task ExecuteWorkflowAsync_UnhandledCommand_ProperlyProcessesSignals ( )
6481
+ {
6482
+ // When our local activity is called, we want to add two signals
6483
+ var workflowId = $ "workflow-{ Guid . NewGuid ( ) } ";
6484
+ var taskQueue = $ "tq-{ Guid . NewGuid ( ) } ";
6485
+ var acts = new UnhandledCommandActivities ( async ( ) =>
6486
+ {
6487
+ var handle = Client . GetWorkflowHandle < UnhandledCommandWorkflow > ( workflowId ) ;
6488
+ await handle . SignalAsync ( wf => wf . SignalAsync ( "one" ) ) ;
6489
+ await handle . SignalAsync ( wf => wf . SignalAsync ( "two" ) ) ;
6490
+ } ) ;
6491
+ // Now start the worker and wait for result
6492
+ await ExecuteWorkerAsync < UnhandledCommandWorkflow > (
6493
+ async worker =>
6494
+ {
6495
+ // Run the workflow
6496
+ var handle = await Client . StartWorkflowAsync (
6497
+ ( UnhandledCommandWorkflow wf ) => wf . RunAsync ( ) ,
6498
+ new ( workflowId , taskQueue ) ) ;
6499
+ // Confirm both signals were seen
6500
+ Assert . Equal ( new List < string > { "one" , "two" } , await handle . GetResultAsync ( ) ) ;
6501
+ // Confirm history has the failed task we expect
6502
+ await AssertMore . TaskFailureEventuallyAsync ( handle , attrs =>
6503
+ Assert . Equal ( WorkflowTaskFailedCause . UnhandledCommand , attrs . Cause ) ) ;
6504
+ } ,
6505
+ new TemporalWorkerOptions ( taskQueue ) . AddAllActivities ( acts ) ) ;
6506
+ }
6507
+
6402
6508
internal static Task AssertTaskFailureContainsEventuallyAsync (
6403
6509
WorkflowHandle handle , string messageContains )
6404
6510
{
0 commit comments