Skip to content

Commit 7efbed4

Browse files
KAFKA-17545: Removing process fetch queue (apache#17534)
The PR removed the process fetch queue as we have moved to share fetch purgatory. Reviewers: Abhinav Dixit <[email protected]>, Jun Rao <[email protected]>
1 parent 6e8df29 commit 7efbed4

File tree

2 files changed

+15
-162
lines changed

2 files changed

+15
-162
lines changed

core/src/main/java/kafka/server/share/SharePartitionManager.java

Lines changed: 15 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@
6969
import java.util.Set;
7070
import java.util.concurrent.CompletableFuture;
7171
import java.util.concurrent.ConcurrentHashMap;
72-
import java.util.concurrent.ConcurrentLinkedQueue;
73-
import java.util.concurrent.atomic.AtomicBoolean;
7472

7573
import scala.jdk.javaapi.CollectionConverters;
7674

@@ -102,16 +100,6 @@ public class SharePartitionManager implements AutoCloseable {
102100
*/
103101
private final ShareSessionCache cache;
104102

105-
/**
106-
* The fetch queue stores the share fetch requests that are waiting to be processed.
107-
*/
108-
private final ConcurrentLinkedQueue<ShareFetchData> fetchQueue;
109-
110-
/**
111-
* The process fetch queue lock is used to ensure that only one thread is processing the fetch queue at a time.
112-
*/
113-
private final AtomicBoolean processFetchQueueLock;
114-
115103
/**
116104
* The group config manager is used to retrieve the values for dynamic group configurations
117105
*/
@@ -184,30 +172,27 @@ private SharePartitionManager(
184172
GroupConfigManager groupConfigManager,
185173
Metrics metrics
186174
) {
187-
this.replicaManager = replicaManager;
188-
this.time = time;
189-
this.cache = cache;
190-
this.partitionCacheMap = partitionCacheMap;
191-
this.fetchQueue = new ConcurrentLinkedQueue<>();
192-
this.processFetchQueueLock = new AtomicBoolean(false);
193-
this.defaultRecordLockDurationMs = defaultRecordLockDurationMs;
194-
this.timer = new SystemTimerReaper("share-group-lock-timeout-reaper",
195-
new SystemTimer("share-group-lock-timeout"));
196-
this.maxDeliveryCount = maxDeliveryCount;
197-
this.maxInFlightMessages = maxInFlightMessages;
198-
this.persister = persister;
199-
this.groupConfigManager = groupConfigManager;
200-
this.shareGroupMetrics = new ShareGroupMetrics(Objects.requireNonNull(metrics), time);
175+
this(replicaManager,
176+
time,
177+
cache,
178+
partitionCacheMap,
179+
defaultRecordLockDurationMs,
180+
new SystemTimerReaper("share-group-lock-timeout-reaper",
181+
new SystemTimer("share-group-lock-timeout")),
182+
maxDeliveryCount,
183+
maxInFlightMessages,
184+
persister,
185+
groupConfigManager,
186+
metrics
187+
);
201188
}
202189

203190
// Visible for testing.
204-
@SuppressWarnings({"checkstyle:ParameterNumber"})
205191
SharePartitionManager(
206192
ReplicaManager replicaManager,
207193
Time time,
208194
ShareSessionCache cache,
209195
Map<SharePartitionKey, SharePartition> partitionCacheMap,
210-
ConcurrentLinkedQueue<ShareFetchData> fetchQueue,
211196
int defaultRecordLockDurationMs,
212197
Timer timer,
213198
int maxDeliveryCount,
@@ -220,8 +205,6 @@ private SharePartitionManager(
220205
this.time = time;
221206
this.cache = cache;
222207
this.partitionCacheMap = partitionCacheMap;
223-
this.fetchQueue = fetchQueue;
224-
this.processFetchQueueLock = new AtomicBoolean(false);
225208
this.defaultRecordLockDurationMs = defaultRecordLockDurationMs;
226209
this.timer = timer;
227210
this.maxDeliveryCount = maxDeliveryCount;
@@ -252,9 +235,7 @@ public CompletableFuture<Map<TopicIdPartition, PartitionData>> fetchMessages(
252235
partitionMaxBytes.keySet(), groupId, fetchParams);
253236

254237
CompletableFuture<Map<TopicIdPartition, PartitionData>> future = new CompletableFuture<>();
255-
ShareFetchData shareFetchData = new ShareFetchData(fetchParams, groupId, memberId, future, partitionMaxBytes);
256-
fetchQueue.add(shareFetchData);
257-
maybeProcessFetchQueue();
238+
processShareFetch(new ShareFetchData(fetchParams, groupId, memberId, future, partitionMaxBytes));
258239

259240
return future;
260241
}
@@ -530,13 +511,6 @@ private void addDelayedShareFetch(DelayedShareFetch delayedShareFetch, Set<Delay
530511
@Override
531512
public void close() throws Exception {
532513
this.timer.close();
533-
this.persister.stop();
534-
if (!fetchQueue.isEmpty()) {
535-
log.warn("Closing SharePartitionManager with pending fetch requests count: {}", fetchQueue.size());
536-
fetchQueue.forEach(shareFetchData -> shareFetchData.future().completeExceptionally(
537-
Errors.BROKER_NOT_AVAILABLE.exception()));
538-
fetchQueue.clear();
539-
}
540514
}
541515

542516
private ShareSessionKey shareSessionKey(String groupId, Uuid memberId) {
@@ -547,31 +521,11 @@ private static String partitionsToLogString(Collection<TopicIdPartition> partiti
547521
return ShareSession.partitionsToLogString(partitions, log.isTraceEnabled());
548522
}
549523

550-
/**
551-
* Recursive function to process all the fetch requests present inside the fetch queue
552-
*/
553524
// Visible for testing.
554-
void maybeProcessFetchQueue() {
555-
if (!acquireProcessFetchQueueLock()) {
556-
// The queue is already being processed hence avoid re-triggering.
557-
return;
558-
}
559-
560-
ShareFetchData shareFetchData = fetchQueue.poll();
561-
if (shareFetchData == null) {
562-
// No more requests to process, so release the lock. Though we should not reach here as the lock
563-
// is acquired only when there are requests in the queue. But still, it's safe to release the lock.
564-
releaseProcessFetchQueueLock();
565-
return;
566-
}
567-
525+
void processShareFetch(ShareFetchData shareFetchData) {
568526
if (shareFetchData.partitionMaxBytes().isEmpty()) {
569527
// If there are no partitions to fetch then complete the future with an empty map.
570528
shareFetchData.future().complete(Collections.emptyMap());
571-
// Release the lock so that other threads can process the queue.
572-
releaseProcessFetchQueueLock();
573-
if (!fetchQueue.isEmpty())
574-
maybeProcessFetchQueue();
575529
return;
576530
}
577531

@@ -590,7 +544,6 @@ void maybeProcessFetchQueue() {
590544
sharePartition.maybeInitialize().whenComplete((result, throwable) -> {
591545
if (throwable != null) {
592546
maybeCompleteInitializationWithException(sharePartitionKey, shareFetchData.future(), throwable);
593-
return;
594547
}
595548
});
596549
});
@@ -611,20 +564,9 @@ void maybeProcessFetchQueue() {
611564
// Add the share fetch to the delayed share fetch purgatory to process the fetch request.
612565
addDelayedShareFetch(new DelayedShareFetch(shareFetchData, replicaManager, this),
613566
delayedShareFetchWatchKeys);
614-
615-
// Release the lock so that other threads can process the queue.
616-
releaseProcessFetchQueueLock();
617-
// If there are more requests in the queue, then process them.
618-
if (!fetchQueue.isEmpty())
619-
maybeProcessFetchQueue();
620-
621567
} catch (Exception e) {
622568
// In case exception occurs then release the locks so queue can be further processed.
623569
log.error("Error processing fetch queue for share partitions", e);
624-
releaseProcessFetchQueueLock();
625-
// If there are more requests in the queue, then process them.
626-
if (!fetchQueue.isEmpty())
627-
maybeProcessFetchQueue();
628570
}
629571
}
630572

@@ -679,15 +621,6 @@ private void maybeCompleteInitializationWithException(
679621
future.completeExceptionally(throwable);
680622
}
681623

682-
// Visible for testing.
683-
boolean acquireProcessFetchQueueLock() {
684-
return processFetchQueueLock.compareAndSet(false, true);
685-
}
686-
687-
private void releaseProcessFetchQueueLock() {
688-
processFetchQueueLock.set(false);
689-
}
690-
691624
private SharePartitionKey sharePartitionKey(String groupId, TopicIdPartition topicIdPartition) {
692625
return new SharePartitionKey(groupId, topicIdPartition);
693626
}

core/src/test/java/kafka/server/share/SharePartitionManagerTest.java

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.apache.kafka.common.TopicIdPartition;
2727
import org.apache.kafka.common.TopicPartition;
2828
import org.apache.kafka.common.Uuid;
29-
import org.apache.kafka.common.errors.BrokerNotAvailableException;
3029
import org.apache.kafka.common.errors.CoordinatorNotAvailableException;
3130
import org.apache.kafka.common.errors.FencedStateEpochException;
3231
import org.apache.kafka.common.errors.InvalidRecordStateException;
@@ -92,7 +91,6 @@
9291
import java.util.Optional;
9392
import java.util.Set;
9493
import java.util.concurrent.CompletableFuture;
95-
import java.util.concurrent.ConcurrentLinkedQueue;
9694
import java.util.concurrent.ExecutionException;
9795
import java.util.concurrent.ExecutorService;
9896
import java.util.concurrent.Executors;
@@ -121,7 +119,6 @@
121119
import static org.mockito.Mockito.mock;
122120
import static org.mockito.Mockito.spy;
123121
import static org.mockito.Mockito.times;
124-
import static org.mockito.Mockito.verify;
125122
import static org.mockito.Mockito.when;
126123

127124
@Timeout(120)
@@ -1253,33 +1250,6 @@ public void testCloseSharePartitionManager() throws Exception {
12531250
sharePartitionManager.close();
12541251
// Verify that the timer object in sharePartitionManager is closed by checking the calls to timer.close() and persister.stop().
12551252
Mockito.verify(timer, times(1)).close();
1256-
Mockito.verify(persister, times(1)).stop();
1257-
}
1258-
1259-
@Test
1260-
public void testCloseShouldCompletePendingFetchRequests() throws Exception {
1261-
String groupId = "grp";
1262-
Uuid memberId = Uuid.randomUuid();
1263-
FetchParams fetchParams = new FetchParams(ApiKeys.SHARE_FETCH.latestVersion(), FetchRequest.ORDINARY_CONSUMER_ID, -1, 0,
1264-
1, 1024 * 1024, FetchIsolation.HIGH_WATERMARK, Optional.empty());
1265-
Uuid fooId = Uuid.randomUuid();
1266-
TopicIdPartition tp0 = new TopicIdPartition(fooId, new TopicPartition("foo", 0));
1267-
Map<TopicIdPartition, Integer> partitionMaxBytes = Collections.singletonMap(tp0, PARTITION_MAX_BYTES);
1268-
1269-
SharePartitionManager sharePartitionManager = SharePartitionManagerBuilder.builder().build();
1270-
1271-
// Acquire the fetch lock so fetch requests keep waiting in the queue.
1272-
assertTrue(sharePartitionManager.acquireProcessFetchQueueLock());
1273-
CompletableFuture<Map<TopicIdPartition, ShareFetchResponseData.PartitionData>> future =
1274-
sharePartitionManager.fetchMessages(groupId, memberId.toString(), fetchParams, partitionMaxBytes);
1275-
// Verify that the fetch request is not completed.
1276-
assertFalse(future.isDone());
1277-
1278-
// Closing the sharePartitionManager closes pending fetch requests in the fetch queue.
1279-
sharePartitionManager.close();
1280-
// Verify that the fetch request is now completed.
1281-
assertTrue(future.isDone());
1282-
assertFutureThrows(future, BrokerNotAvailableException.class);
12831253
}
12841254

12851255
@Test
@@ -1640,49 +1610,6 @@ public void testAcknowledgeEmptyPartitionCacheMap() {
16401610
assertEquals(Errors.UNKNOWN_TOPIC_OR_PARTITION.code(), result.get(tp).errorCode());
16411611
}
16421612

1643-
@Test
1644-
public void testFetchQueueProcessingWhenFrontItemIsEmpty() {
1645-
String groupId = "grp";
1646-
String memberId = Uuid.randomUuid().toString();
1647-
FetchParams fetchParams = new FetchParams(ApiKeys.SHARE_FETCH.latestVersion(), FetchRequest.ORDINARY_CONSUMER_ID, -1, DELAYED_SHARE_FETCH_MAX_WAIT_MS,
1648-
1, 1024 * 1024, FetchIsolation.HIGH_WATERMARK, Optional.empty());
1649-
TopicIdPartition tp0 = new TopicIdPartition(Uuid.randomUuid(), new TopicPartition("foo", 0));
1650-
Map<TopicIdPartition, Integer> partitionMaxBytes = new HashMap<>();
1651-
partitionMaxBytes.put(tp0, PARTITION_MAX_BYTES);
1652-
1653-
final Time time = new MockTime();
1654-
ReplicaManager replicaManager = mock(ReplicaManager.class);
1655-
1656-
ShareFetchData shareFetchData1 = new ShareFetchData(
1657-
fetchParams, groupId, memberId, new CompletableFuture<>(), Collections.emptyMap());
1658-
ShareFetchData shareFetchData2 = new ShareFetchData(
1659-
fetchParams, groupId, memberId, new CompletableFuture<>(), partitionMaxBytes);
1660-
1661-
ConcurrentLinkedQueue<ShareFetchData> fetchQueue = new ConcurrentLinkedQueue<>();
1662-
// First request added to fetch queue is empty i.e. no topic partitions to fetch.
1663-
fetchQueue.add(shareFetchData1);
1664-
// Second request added to fetch queue has a topic partition to fetch.
1665-
fetchQueue.add(shareFetchData2);
1666-
1667-
DelayedOperationPurgatory<DelayedShareFetch> delayedShareFetchPurgatory = new DelayedOperationPurgatory<>(
1668-
"TestShareFetch", mockTimer, replicaManager.localBrokerId(),
1669-
DELAYED_SHARE_FETCH_PURGATORY_PURGE_INTERVAL, true, true);
1670-
mockReplicaManagerDelayedShareFetch(replicaManager, delayedShareFetchPurgatory);
1671-
1672-
SharePartitionManager sharePartitionManager = SharePartitionManagerBuilder.builder()
1673-
.withReplicaManager(replicaManager)
1674-
.withTime(time)
1675-
.withTimer(mockTimer)
1676-
.withFetchQueue(fetchQueue).build();
1677-
1678-
doAnswer(invocation -> buildLogReadResult(partitionMaxBytes.keySet())).when(replicaManager).readFromLog(any(), any(), any(ReplicaQuota.class), anyBoolean());
1679-
1680-
sharePartitionManager.maybeProcessFetchQueue();
1681-
1682-
// Verifying that the second item in the fetchQueue is processed, even though the first item is empty.
1683-
verify(replicaManager, times(1)).readFromLog(any(), any(), any(ReplicaQuota.class), anyBoolean());
1684-
}
1685-
16861613
@Test
16871614
public void testAcknowledgeCompletesDelayedShareFetchRequest() {
16881615
String groupId = "grp";
@@ -2314,7 +2241,6 @@ static class SharePartitionManagerBuilder {
23142241
private Persister persister = NoOpShareStatePersister.getInstance();
23152242
private Timer timer = new MockTimer();
23162243
private Metrics metrics = new Metrics();
2317-
private ConcurrentLinkedQueue<ShareFetchData> fetchQueue = new ConcurrentLinkedQueue<>();
23182244

23192245
private SharePartitionManagerBuilder withReplicaManager(ReplicaManager replicaManager) {
23202246
this.replicaManager = replicaManager;
@@ -2351,11 +2277,6 @@ private SharePartitionManagerBuilder withMetrics(Metrics metrics) {
23512277
return this;
23522278
}
23532279

2354-
private SharePartitionManagerBuilder withFetchQueue(ConcurrentLinkedQueue<ShareFetchData> fetchQueue) {
2355-
this.fetchQueue = fetchQueue;
2356-
return this;
2357-
}
2358-
23592280
public static SharePartitionManagerBuilder builder() {
23602281
return new SharePartitionManagerBuilder();
23612282
}
@@ -2365,7 +2286,6 @@ public SharePartitionManager build() {
23652286
time,
23662287
cache,
23672288
partitionCacheMap,
2368-
fetchQueue,
23692289
DEFAULT_RECORD_LOCK_DURATION_MS,
23702290
timer,
23712291
MAX_DELIVERY_COUNT,

0 commit comments

Comments
 (0)