@@ -153,13 +153,24 @@ public void testDelayedShareFetchTryCompleteReturnsFalseDueToNonAcquirablePartit
153153 when (sp0 .canAcquireRecords ()).thenReturn (false );
154154 when (sp1 .canAcquireRecords ()).thenReturn (false );
155155
156+ Partition p0 = mock (Partition .class );
157+ when (p0 .isLeader ()).thenReturn (true );
158+
159+ Partition p1 = mock (Partition .class );
160+ when (p1 .isLeader ()).thenReturn (true );
161+
162+ ReplicaManager replicaManager = mock (ReplicaManager .class );
163+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
164+ when (replicaManager .getPartitionOrException (tp1 .topicPartition ())).thenReturn (p1 );
165+
156166 ShareGroupMetrics shareGroupMetrics = new ShareGroupMetrics (new MockTime ());
157167 Uuid fetchId = Uuid .randomUuid ();
158168 DelayedShareFetch delayedShareFetch = spy (DelayedShareFetchBuilder .builder ()
159169 .withShareFetchData (shareFetch )
160170 .withSharePartitions (sharePartitions )
161171 .withShareGroupMetrics (shareGroupMetrics )
162172 .withFetchId (fetchId )
173+ .withReplicaManager (replicaManager )
163174 .build ());
164175
165176 when (sp0 .maybeAcquireFetchLock (fetchId )).thenReturn (true );
@@ -218,6 +229,15 @@ public void testTryCompleteWhenMinBytesNotSatisfiedOnFirstFetch() {
218229
219230 PartitionMaxBytesStrategy partitionMaxBytesStrategy = mockPartitionMaxBytes (Set .of (tp0 ));
220231
232+ Partition p0 = mock (Partition .class );
233+ when (p0 .isLeader ()).thenReturn (true );
234+
235+ Partition p1 = mock (Partition .class );
236+ when (p1 .isLeader ()).thenReturn (true );
237+
238+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
239+ when (replicaManager .getPartitionOrException (tp1 .topicPartition ())).thenReturn (p1 );
240+
221241 Time time = mock (Time .class );
222242 when (time .hiResClockMs ()).thenReturn (100L ).thenReturn (110L );
223243 ShareGroupMetrics shareGroupMetrics = new ShareGroupMetrics (time );
@@ -287,6 +307,15 @@ public void testTryCompleteWhenMinBytesNotSatisfiedOnSubsequentFetch() {
287307 mockTopicIdPartitionFetchBytes (replicaManager , tp0 , hwmOffsetMetadata );
288308 BiConsumer <SharePartitionKey , Throwable > exceptionHandler = mockExceptionHandler ();
289309
310+ Partition p0 = mock (Partition .class );
311+ when (p0 .isLeader ()).thenReturn (true );
312+
313+ Partition p1 = mock (Partition .class );
314+ when (p1 .isLeader ()).thenReturn (true );
315+
316+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
317+ when (replicaManager .getPartitionOrException (tp1 .topicPartition ())).thenReturn (p1 );
318+
290319 Uuid fetchId = Uuid .randomUuid ();
291320 DelayedShareFetch delayedShareFetch = spy (DelayedShareFetchBuilder .builder ()
292321 .withShareFetchData (shareFetch )
@@ -580,6 +609,19 @@ public void testForceCompleteTriggersDelayedActionsQueue() {
580609 List <DelayedOperationKey > delayedShareFetchWatchKeys = new ArrayList <>();
581610 topicIdPartitions1 .forEach (topicIdPartition -> delayedShareFetchWatchKeys .add (new DelayedShareFetchGroupKey (groupId , topicIdPartition .topicId (), topicIdPartition .partition ())));
582611
612+ Partition p0 = mock (Partition .class );
613+ when (p0 .isLeader ()).thenReturn (true );
614+
615+ Partition p1 = mock (Partition .class );
616+ when (p1 .isLeader ()).thenReturn (true );
617+
618+ Partition p2 = mock (Partition .class );
619+ when (p2 .isLeader ()).thenReturn (true );
620+
621+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
622+ when (replicaManager .getPartitionOrException (tp1 .topicPartition ())).thenReturn (p1 );
623+ when (replicaManager .getPartitionOrException (tp2 .topicPartition ())).thenReturn (p2 );
624+
583625 Uuid fetchId1 = Uuid .randomUuid ();
584626 DelayedShareFetch delayedShareFetch1 = DelayedShareFetchTest .DelayedShareFetchBuilder .builder ()
585627 .withShareFetchData (shareFetch1 )
@@ -737,6 +779,12 @@ public void testExceptionInMinBytesCalculation() {
737779 when (time .hiResClockMs ()).thenReturn (100L ).thenReturn (110L ).thenReturn (170L );
738780 ShareGroupMetrics shareGroupMetrics = new ShareGroupMetrics (time );
739781 Uuid fetchId = Uuid .randomUuid ();
782+
783+ Partition p0 = mock (Partition .class );
784+ when (p0 .isLeader ()).thenReturn (true );
785+
786+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
787+
740788 DelayedShareFetch delayedShareFetch = spy (DelayedShareFetchBuilder .builder ()
741789 .withShareFetchData (shareFetch )
742790 .withSharePartitions (sharePartitions )
@@ -881,10 +929,18 @@ public void testLocksReleasedAcquireException() {
881929 BROKER_TOPIC_STATS );
882930
883931 Uuid fetchId = Uuid .randomUuid ();
932+
933+ Partition p0 = mock (Partition .class );
934+ when (p0 .isLeader ()).thenReturn (true );
935+
936+ ReplicaManager replicaManager = mock (ReplicaManager .class );
937+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
938+
884939 DelayedShareFetch delayedShareFetch = DelayedShareFetchTest .DelayedShareFetchBuilder .builder ()
885940 .withShareFetchData (shareFetch )
886941 .withSharePartitions (sharePartitions )
887942 .withFetchId (fetchId )
943+ .withReplicaManager (replicaManager )
888944 .build ();
889945
890946 when (sp0 .maybeAcquireFetchLock (fetchId )).thenReturn (true );
@@ -1263,6 +1319,19 @@ public void testRemoteStorageFetchTryCompleteReturnsFalse() {
12631319 when (remoteLogManager .asyncRead (any (), any ())).thenReturn (mock (Future .class ));
12641320 when (replicaManager .remoteLogManager ()).thenReturn (Option .apply (remoteLogManager ));
12651321
1322+ Partition p0 = mock (Partition .class );
1323+ when (p0 .isLeader ()).thenReturn (true );
1324+
1325+ Partition p1 = mock (Partition .class );
1326+ when (p1 .isLeader ()).thenReturn (true );
1327+
1328+ Partition p2 = mock (Partition .class );
1329+ when (p2 .isLeader ()).thenReturn (true );
1330+
1331+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
1332+ when (replicaManager .getPartitionOrException (tp1 .topicPartition ())).thenReturn (p1 );
1333+ when (replicaManager .getPartitionOrException (tp2 .topicPartition ())).thenReturn (p2 );
1334+
12661335 Uuid fetchId = Uuid .randomUuid ();
12671336 DelayedShareFetch delayedShareFetch = spy (DelayedShareFetchBuilder .builder ()
12681337 .withShareFetchData (shareFetch )
@@ -1288,6 +1357,70 @@ public void testRemoteStorageFetchTryCompleteReturnsFalse() {
12881357 delayedShareFetch .lock ().unlock ();
12891358 }
12901359
1360+ @ Test
1361+ public void testRemoteStorageFetchPartitionLeaderChanged () {
1362+ ReplicaManager replicaManager = mock (ReplicaManager .class );
1363+ TopicIdPartition tp0 = new TopicIdPartition (Uuid .randomUuid (), new TopicPartition ("foo" , 0 ));
1364+
1365+ SharePartition sp0 = mock (SharePartition .class );
1366+
1367+ when (sp0 .canAcquireRecords ()).thenReturn (true );
1368+
1369+ LinkedHashMap <TopicIdPartition , SharePartition > sharePartitions = new LinkedHashMap <>();
1370+ sharePartitions .put (tp0 , sp0 );
1371+
1372+ ShareFetch shareFetch = new ShareFetch (FETCH_PARAMS , "grp" , Uuid .randomUuid ().toString (),
1373+ new CompletableFuture <>(), List .of (tp0 ), BATCH_SIZE , MAX_FETCH_RECORDS ,
1374+ BROKER_TOPIC_STATS );
1375+
1376+ when (sp0 .nextFetchOffset ()).thenReturn (10L );
1377+
1378+ // Fetch offset does not match with the cached entry for sp0, hence, a replica manager fetch will happen for sp0.
1379+ when (sp0 .fetchOffsetMetadata (anyLong ())).thenReturn (Optional .empty ());
1380+
1381+ // Mocking remote storage read result for tp0.
1382+ doAnswer (invocation -> buildLocalAndRemoteFetchResult (Set .of (), Set .of (tp0 ))).when (replicaManager ).readFromLog (any (), any (), any (ReplicaQuota .class ), anyBoolean ());
1383+
1384+ // Remote fetch related mocks. Remote fetch object does not complete within tryComplete in this mock.
1385+ RemoteLogManager remoteLogManager = mock (RemoteLogManager .class );
1386+ when (remoteLogManager .asyncRead (any (), any ())).thenReturn (mock (Future .class ));
1387+ when (replicaManager .remoteLogManager ()).thenReturn (Option .apply (remoteLogManager ));
1388+
1389+ Partition p0 = mock (Partition .class );
1390+ when (p0 .isLeader ()).thenReturn (false );
1391+
1392+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
1393+
1394+ Uuid fetchId = Uuid .randomUuid ();
1395+ DelayedShareFetch delayedShareFetch = spy (DelayedShareFetchBuilder .builder ()
1396+ .withShareFetchData (shareFetch )
1397+ .withSharePartitions (sharePartitions )
1398+ .withReplicaManager (replicaManager )
1399+ .withPartitionMaxBytesStrategy (mockPartitionMaxBytes (Set .of (tp0 )))
1400+ .withFetchId (fetchId )
1401+ .build ());
1402+
1403+ // All the topic partitions are acquirable.
1404+ when (sp0 .maybeAcquireFetchLock (fetchId )).thenReturn (true );
1405+
1406+ // Mock the behaviour of replica manager such that remote storage fetch completion timer task completes on adding it to the watch queue.
1407+ doAnswer (invocationOnMock -> {
1408+ TimerTask timerTask = invocationOnMock .getArgument (0 );
1409+ timerTask .run ();
1410+ return null ;
1411+ }).when (replicaManager ).addShareFetchTimerRequest (any ());
1412+
1413+ assertFalse (delayedShareFetch .isCompleted ());
1414+ assertTrue (delayedShareFetch .tryComplete ());
1415+ assertTrue (delayedShareFetch .isCompleted ());
1416+ // Remote fetch object gets created for delayed share fetch object.
1417+ assertNotNull (delayedShareFetch .pendingRemoteFetches ());
1418+ // Verify the locks are released for local log read topic partitions tp0.
1419+ Mockito .verify (delayedShareFetch , times (1 )).releasePartitionLocks (Set .of (tp0 ));
1420+ assertTrue (delayedShareFetch .lock ().tryLock ());
1421+ delayedShareFetch .lock ().unlock ();
1422+ }
1423+
12911424 @ Test
12921425 public void testRemoteStorageFetchTryCompleteThrowsException () {
12931426 ReplicaManager replicaManager = mock (ReplicaManager .class );
@@ -1516,6 +1649,16 @@ public void testRemoteStorageFetchRequestCompletionOnFutureCompletionFailure() {
15161649 when (replicaManager .remoteLogManager ()).thenReturn (Option .apply (remoteLogManager ));
15171650
15181651 Uuid fetchId = Uuid .randomUuid ();
1652+
1653+ Partition p0 = mock (Partition .class );
1654+ when (p0 .isLeader ()).thenReturn (true );
1655+
1656+ Partition p1 = mock (Partition .class );
1657+ when (p1 .isLeader ()).thenReturn (true );
1658+
1659+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
1660+ when (replicaManager .getPartitionOrException (tp1 .topicPartition ())).thenReturn (p1 );
1661+
15191662 DelayedShareFetch delayedShareFetch = spy (DelayedShareFetchBuilder .builder ()
15201663 .withShareFetchData (shareFetch )
15211664 .withSharePartitions (sharePartitions )
@@ -1586,6 +1729,12 @@ public void testRemoteStorageFetchRequestCompletionOnFutureCompletionSuccessfull
15861729 when (replicaManager .remoteLogManager ()).thenReturn (Option .apply (remoteLogManager ));
15871730
15881731 Uuid fetchId = Uuid .randomUuid ();
1732+
1733+ Partition p0 = mock (Partition .class );
1734+ when (p0 .isLeader ()).thenReturn (true );
1735+
1736+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
1737+
15891738 DelayedShareFetch delayedShareFetch = spy (DelayedShareFetchBuilder .builder ()
15901739 .withShareFetchData (shareFetch )
15911740 .withSharePartitions (sharePartitions )
@@ -1679,6 +1828,19 @@ public void testRemoteStorageFetchRequestCompletionAlongWithLocalLogRead() {
16791828 }).when (remoteLogManager ).asyncRead (any (), any ());
16801829 when (replicaManager .remoteLogManager ()).thenReturn (Option .apply (remoteLogManager ));
16811830
1831+ Partition p0 = mock (Partition .class );
1832+ when (p0 .isLeader ()).thenReturn (true );
1833+
1834+ Partition p1 = mock (Partition .class );
1835+ when (p1 .isLeader ()).thenReturn (true );
1836+
1837+ Partition p2 = mock (Partition .class );
1838+ when (p2 .isLeader ()).thenReturn (true );
1839+
1840+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
1841+ when (replicaManager .getPartitionOrException (tp1 .topicPartition ())).thenReturn (p1 );
1842+ when (replicaManager .getPartitionOrException (tp2 .topicPartition ())).thenReturn (p2 );
1843+
16821844 Uuid fetchId = Uuid .randomUuid ();
16831845 DelayedShareFetch delayedShareFetch = spy (DelayedShareFetchBuilder .builder ()
16841846 .withShareFetchData (shareFetch )
@@ -1761,6 +1923,16 @@ public void testRemoteStorageFetchHappensForAllTopicPartitions() {
17611923 when (replicaManager .remoteLogManager ()).thenReturn (Option .apply (remoteLogManager ));
17621924
17631925 Uuid fetchId = Uuid .randomUuid ();
1926+
1927+ Partition p0 = mock (Partition .class );
1928+ when (p0 .isLeader ()).thenReturn (true );
1929+
1930+ Partition p1 = mock (Partition .class );
1931+ when (p1 .isLeader ()).thenReturn (true );
1932+
1933+ when (replicaManager .getPartitionOrException (tp0 .topicPartition ())).thenReturn (p0 );
1934+ when (replicaManager .getPartitionOrException (tp1 .topicPartition ())).thenReturn (p1 );
1935+
17641936 DelayedShareFetch delayedShareFetch = spy (DelayedShareFetchBuilder .builder ()
17651937 .withShareFetchData (shareFetch )
17661938 .withSharePartitions (sharePartitions )
0 commit comments