@@ -564,6 +564,73 @@ public async Task TestDeclarationOfManyAutoDeleteQueuesWithTransientConsumer()
564
564
AssertRecordedQueues ( ( RabbitMQ . Client . Framing . Impl . AutorecoveringConnection ) _conn , 0 ) ;
565
565
}
566
566
567
+ [ Fact ]
568
+ public async Task TestCreateChannelWithinAsyncConsumerCallback_GH650 ( )
569
+ {
570
+ string exchangeName = GenerateExchangeName ( ) ;
571
+ string queue1Name = GenerateQueueName ( ) ;
572
+ string queue2Name = GenerateQueueName ( ) ;
573
+
574
+ var tcs = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
575
+ using var cts = new CancellationTokenSource ( WaitSpan ) ;
576
+ using CancellationTokenRegistration ctr = cts . Token . Register ( ( ) =>
577
+ {
578
+ tcs . SetCanceled ( ) ;
579
+ } ) ;
580
+
581
+ _conn . ConnectionShutdown += ( o , ea ) =>
582
+ {
583
+ HandleConnectionShutdown ( _conn , ea , ( args ) =>
584
+ {
585
+ MaybeSetException ( ea , tcs ) ;
586
+ } ) ;
587
+ } ;
588
+
589
+ _channel . ChannelShutdown += ( o , ea ) =>
590
+ {
591
+ HandleChannelShutdown ( _channel , ea , ( args ) =>
592
+ {
593
+ MaybeSetException ( ea , tcs ) ;
594
+ } ) ;
595
+ } ;
596
+
597
+ // queue1 -> produce click to queue2
598
+ // click -> exchange
599
+ // queue2 -> consume click from queue1
600
+ await _channel . ExchangeDeclareAsync ( exchangeName , ExchangeType . Direct , autoDelete : true ) ;
601
+ await _channel . QueueDeclareAsync ( queue1Name ) ;
602
+ await _channel . QueueBindAsync ( queue1Name , exchangeName , queue1Name ) ;
603
+ await _channel . QueueDeclareAsync ( queue2Name ) ;
604
+ await _channel . QueueBindAsync ( queue2Name , exchangeName , queue2Name ) ;
605
+
606
+ var consumer1 = new AsyncEventingBasicConsumer ( _channel ) ;
607
+ consumer1 . Received += async ( sender , args ) =>
608
+ {
609
+ using ( IChannel innerChannel = await _conn . CreateChannelAsync ( ) )
610
+ {
611
+ await innerChannel . ConfirmSelectAsync ( ) ;
612
+ await innerChannel . BasicPublishAsync ( exchangeName , queue2Name , mandatory : true ) ;
613
+ await innerChannel . WaitForConfirmsOrDieAsync ( ) ;
614
+ await innerChannel . CloseAsync ( ) ;
615
+ }
616
+ } ;
617
+ await _channel . BasicConsumeAsync ( queue1Name , autoAck : true , consumer1 ) ;
618
+
619
+ var consumer2 = new AsyncEventingBasicConsumer ( _channel ) ;
620
+ consumer2 . Received += async ( sender , args ) =>
621
+ {
622
+ tcs . TrySetResult ( true ) ;
623
+ await Task . Yield ( ) ;
624
+ } ;
625
+ await _channel . BasicConsumeAsync ( queue2Name , autoAck : true , consumer2 ) ;
626
+
627
+ await _channel . ConfirmSelectAsync ( ) ;
628
+ await _channel . BasicPublishAsync ( exchangeName , queue1Name , body : GetRandomBody ( 1024 ) ) ;
629
+ await _channel . WaitForConfirmsOrDieAsync ( ) ;
630
+
631
+ Assert . True ( await tcs . Task ) ;
632
+ }
633
+
567
634
private static void SetException ( Exception ex , params TaskCompletionSource < bool > [ ] tcsAry )
568
635
{
569
636
foreach ( TaskCompletionSource < bool > tcs in tcsAry )
0 commit comments