@@ -182,10 +182,21 @@ Mocks InitCluster()
182
182
return new Mocks { Cluster = cluster , Node = node , Group = group , HeartbeatCalled = heartbeatEvent } ;
183
183
}
184
184
185
- private void WaitForCallToHeartbeat ( Mocks mock )
185
+ private void WaitOneSecondMaxForEvent ( string name , AutoResetEvent ev )
186
186
{
187
- if ( ! mock . HeartbeatCalled . WaitOne ( TimeSpan . FromSeconds ( 1 ) ) )
188
- Assert . Fail ( "We waited 1 sec for a hearbeat to happen, but it never did." ) ;
187
+ if ( ! ev . WaitOne ( TimeSpan . FromSeconds ( 1 ) ) )
188
+ {
189
+ Assert . Fail ( "We waited 1 sec for " + name + " to happen, but it never did." ) ;
190
+ }
191
+ }
192
+
193
+ private async Task HeartbeatFinishedProcessing ( Mocks mock , ConsumeRouter router )
194
+ {
195
+ // First we wait to be sure that a heartbeat has started being processed
196
+ WaitOneSecondMaxForEvent ( "heatbeat" , mock . HeartbeatCalled ) ;
197
+ // Then we wait to be sure that the current message is finished processing
198
+ // (this message being the heartbeat or a following message)
199
+ await router . StopProcessingTask ( ) ;
189
200
}
190
201
191
202
[ Test ]
@@ -505,7 +516,7 @@ public void TestConsumer_ConsumerGroupStartConsume()
505
516
mocks . Node . Verify ( n => n . Fetch ( It . IsAny < FetchMessage > ( ) ) , Times . Once ) ; // 1 partition with specific offset
506
517
mocks . Node . Verify ( n => n . Offset ( It . IsAny < OffsetMessage > ( ) ) , Times . Once ) ; // 1 partition with offset -1
507
518
508
- WaitForCallToHeartbeat ( mocks ) ;
519
+ WaitOneSecondMaxForEvent ( "heatbeat" , mocks . HeartbeatCalled ) ;
509
520
510
521
mocks . Group . Verify ( g => g . Heartbeat ( ) ) ;
511
522
@@ -540,27 +551,30 @@ public void TestConsumer_ConsumerGroupStartConsume()
540
551
} } ) ;
541
552
542
553
mocks . Node . Verify ( n => n . Fetch ( It . IsAny < FetchMessage > ( ) ) , Times . Exactly ( 2 ) ) ; // response should have triggered one more fetch
543
- if ( ! commitEvent . WaitOne ( TimeSpan . FromSeconds ( 1 ) ) )
544
- Assert . Fail ( "We waited 1 sec for a commit from the group, it did not happen" ) ;
554
+ WaitOneSecondMaxForEvent ( "commit" , commitEvent ) ;
545
555
mocks . Group . Verify ( g => g . Commit ( It . IsAny < IEnumerable < TopicData < OffsetCommitPartitionData > > > ( ) ) ) ; // should have auto commited
546
556
547
557
consumer . Stop ( ) . Wait ( ) ;
548
558
}
549
559
550
560
[ Test ]
551
- public void TestConsumer_ConsumerGroupRestartConsume ( )
561
+ public async Task TestConsumer_ConsumerGroupRestartConsume ( )
552
562
{
553
563
var mocks = InitCluster ( ) ;
554
564
var consumer = new ConsumeRouter ( mocks . Cluster . Object ,
555
565
new Configuration { TaskScheduler = new CurrentThreadTaskScheduler ( ) , ConsumeBatchSize = 1 } , 1 ) ;
556
566
567
+ var consumerStartEvent = new AutoResetEvent ( false ) ;
568
+ var consumerStopEvent = new AutoResetEvent ( false ) ;
569
+ consumer . ConsumerStopped += ( ) => { consumerStopEvent . Set ( ) ; } ;
570
+
557
571
consumer . StartConsumeSubscription ( mocks . Group . Object , new [ ] { "the topic" } ) ;
558
572
559
573
mocks . Group . Verify ( g => g . Join ( It . IsAny < IEnumerable < string > > ( ) ) , Times . Once ) ;
560
574
mocks . Node . Verify ( n => n . Fetch ( It . IsAny < FetchMessage > ( ) ) , Times . Once ) ; // 1 partition with specific offset
561
575
mocks . Node . Verify ( n => n . Offset ( It . IsAny < OffsetMessage > ( ) ) , Times . Once ) ; // 1 partition with offset -1
562
576
563
- WaitForCallToHeartbeat ( mocks ) ;
577
+ WaitOneSecondMaxForEvent ( "heatbeat" , mocks . HeartbeatCalled ) ;
564
578
565
579
mocks . Group . Verify ( g => g . Heartbeat ( ) ) ;
566
580
@@ -594,9 +608,11 @@ public void TestConsumer_ConsumerGroupRestartConsume()
594
608
}
595
609
} } ) ;
596
610
597
- mocks . Node . Verify ( n => n . Fetch ( It . IsAny < FetchMessage > ( ) ) , Times . Exactly ( 2 ) ) ; // response should have triggered one more fetch
598
611
599
612
consumer . StopConsume ( "the topic" , Partitions . All , Offsets . Now ) ;
613
+ WaitOneSecondMaxForEvent ( "stop" , consumerStopEvent ) ;
614
+ mocks . Node . Verify ( n => n . Fetch ( It . IsAny < FetchMessage > ( ) ) ,
615
+ Times . Exactly ( 2 ) ) ; // response should have triggered one more fetch
600
616
601
617
consumer . Acknowledge ( new CommonAcknowledgement < FetchResponse >
602
618
{
@@ -628,8 +644,10 @@ public void TestConsumer_ConsumerGroupRestartConsume()
628
644
}
629
645
} } ) ;
630
646
647
+ consumer . ConsumerStarted += ( ) => { consumerStartEvent . Set ( ) ; } ;
631
648
consumer . StartConsume ( "the topic" , Partitions . All , Offsets . Now ) ;
632
649
650
+ WaitOneSecondMaxForEvent ( "start" , consumerStartEvent ) ;
633
651
mocks . Node . Verify ( n => n . Fetch ( It . IsAny < FetchMessage > ( ) ) , Times . Exactly ( 3 ) ) ;
634
652
635
653
consumer . Stop ( ) . Wait ( ) ;
@@ -657,7 +675,7 @@ public void TestConsumer_ConsumerGroupCommit()
657
675
658
676
consumer . StartConsumeSubscription ( mocks . Group . Object , new [ ] { "the topic" } ) ;
659
677
660
- WaitForCallToHeartbeat ( mocks ) ;
678
+ WaitOneSecondMaxForEvent ( "heatbeat" , mocks . HeartbeatCalled ) ;
661
679
662
680
consumer . Acknowledge ( new CommonAcknowledgement < FetchResponse >
663
681
{
@@ -730,7 +748,7 @@ public async Task TestConsumer_ConsumerGroupCommitAsync()
730
748
}
731
749
732
750
[ Test ]
733
- public void TestConsumer_ConsumerGroupHeartbeatErrors ( )
751
+ public async Task TestConsumer_ConsumerGroupHeartbeatErrors ( )
734
752
{
735
753
var mocks = InitCluster ( ) ;
736
754
mocks . Group . SetupGet ( g => g . Configuration )
@@ -743,7 +761,7 @@ public void TestConsumer_ConsumerGroupHeartbeatErrors()
743
761
744
762
consumer . StartConsumeSubscription ( mocks . Group . Object , new [ ] { "the topic" } ) ;
745
763
746
- WaitForCallToHeartbeat ( mocks ) ;
764
+ await HeartbeatFinishedProcessing ( mocks , consumer ) ;
747
765
748
766
// At least 2 Join (one on start, one on next heartbeat)
749
767
mocks . Group . Verify ( g => g . Join ( It . IsAny < IEnumerable < string > > ( ) ) , Times . AtLeast ( 2 ) ) ;
@@ -761,7 +779,7 @@ public void TestConsumer_ConsumerGroupHeartbeatErrors()
761
779
762
780
consumer . StartConsumeSubscription ( mocks . Group . Object , new [ ] { "the topic" } ) ;
763
781
764
- WaitForCallToHeartbeat ( mocks ) ;
782
+ await HeartbeatFinishedProcessing ( mocks , consumer ) ;
765
783
766
784
mocks . Group . Verify ( g => g . Join ( It . IsAny < IEnumerable < string > > ( ) ) , Times . AtLeast ( 2 ) ) ;
767
785
// No Commit tried in case of ""hard" heartbeat errors
@@ -823,7 +841,9 @@ public async Task TestConsumer_RaisesPartitionsRevokedOnRebalance()
823
841
{
824
842
var mocks = InitCluster ( ) ;
825
843
826
- mocks . Group . Setup ( g => g . Heartbeat ( ) ) . ReturnsAsync ( ErrorCode . RebalanceInProgress ) ;
844
+ mocks . Group . Setup ( g => g . Heartbeat ( ) )
845
+ . ReturnsAsync ( ErrorCode . RebalanceInProgress )
846
+ . Callback ( ( ) => mocks . HeartbeatCalled . Set ( ) ) ;
827
847
828
848
mocks . Group . SetupGet ( g => g . Configuration ) . Returns (
829
849
new ConsumerGroupConfiguration { AutoCommitEveryMs = - 1 , SessionTimeoutMs = 10 } ) ;
@@ -841,7 +861,8 @@ public async Task TestConsumer_RaisesPartitionsRevokedOnRebalance()
841
861
consumer . PartitionsRevoked += ( ) => partitionsRevokedEventIsCalled = true ;
842
862
843
863
consumer . StartConsumeSubscription ( mocks . Group . Object , new [ ] { "the topic" } ) ;
844
- Thread . Sleep ( 20 ) ;
864
+
865
+ await HeartbeatFinishedProcessing ( mocks , consumer ) ;
845
866
846
867
Assert . That ( partitionsRevokedEventIsCalled , Is . True ) ;
847
868
0 commit comments