-
Notifications
You must be signed in to change notification settings - Fork 14.8k
KAFKA-19340: Move DelayedRemoteFetch to the storage module #19876
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7ab02f4
052f60a
37aa96f
e5d1abb
46dd310
1fac1e4
52156c0
20ec186
de54d11
67c3c18
6aa0df8
b403181
544e04f
941b2d3
d222a5a
ea5539d
24df252
11f7708
57c4e9b
fd4e3f9
cdbdc00
07db3cc
5184d31
ef1ce23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -56,16 +56,16 @@ import org.apache.kafka.server.config.ReplicationConfigs | |
| import org.apache.kafka.server.log.remote.storage.RemoteLogManager | ||
| import org.apache.kafka.server.metrics.KafkaMetricsGroup | ||
| import org.apache.kafka.server.network.BrokerEndPoint | ||
| import org.apache.kafka.server.purgatory.{DelayedDeleteRecords, DelayedOperationPurgatory, DelayedRemoteListOffsets, DeleteRecordsPartitionStatus, ListOffsetsPartitionStatus, TopicPartitionOperationKey} | ||
| import org.apache.kafka.server.purgatory.{DelayedDeleteRecords, DelayedOperationPurgatory, DelayedRemoteFetch, DelayedRemoteListOffsets, DeleteRecordsPartitionStatus, ListOffsetsPartitionStatus, TopicPartitionOperationKey} | ||
| import org.apache.kafka.server.share.fetch.{DelayedShareFetchKey, DelayedShareFetchPartitionKey} | ||
| import org.apache.kafka.server.storage.log.{FetchParams, FetchPartitionData} | ||
| import org.apache.kafka.server.transaction.AddPartitionsToTxnManager | ||
| import org.apache.kafka.server.transaction.AddPartitionsToTxnManager.TransactionSupportedOperation | ||
| import org.apache.kafka.server.util.timer.{SystemTimer, TimerTask} | ||
| import org.apache.kafka.server.util.{Scheduler, ShutdownableThread} | ||
| import org.apache.kafka.server.{ActionQueue, DelayedActionQueue, LogReadResult, common} | ||
| import org.apache.kafka.server.{ActionQueue, DelayedActionQueue, common} | ||
| import org.apache.kafka.storage.internals.checkpoint.{LazyOffsetCheckpoints, OffsetCheckpointFile, OffsetCheckpoints} | ||
| import org.apache.kafka.storage.internals.log.{AppendOrigin, FetchDataInfo, LeaderHwChange, LogAppendInfo, LogConfig, LogDirFailureChannel, LogOffsetMetadata, LogReadInfo, OffsetResultHolder, RecordValidationException, RemoteLogReadResult, RemoteStorageFetchInfo, UnifiedLog, VerificationGuard} | ||
| import org.apache.kafka.storage.internals.log.{AppendOrigin, FetchDataInfo, FetchPartitionStatus, LeaderHwChange, LogAppendInfo, LogConfig, LogDirFailureChannel, LogOffsetMetadata, LogReadInfo, LogReadResult, OffsetResultHolder, RecordValidationException, RemoteLogReadResult, RemoteStorageFetchInfo, UnifiedLog, VerificationGuard} | ||
| import org.apache.kafka.storage.log.metrics.BrokerTopicStats | ||
|
|
||
| import java.io.File | ||
|
|
@@ -188,19 +188,7 @@ object ReplicaManager { | |
| -1L, | ||
| -1L, | ||
| OptionalLong.empty(), | ||
| Optional.of(e)) | ||
| } | ||
|
|
||
| def createLogReadResult(e: Throwable): LogReadResult = { | ||
| new LogReadResult(new FetchDataInfo(LogOffsetMetadata.UNKNOWN_OFFSET_METADATA, MemoryRecords.EMPTY), | ||
| Optional.empty(), | ||
| UnifiedLog.UNKNOWN_OFFSET, | ||
| UnifiedLog.UNKNOWN_OFFSET, | ||
| UnifiedLog.UNKNOWN_OFFSET, | ||
| UnifiedLog.UNKNOWN_OFFSET, | ||
| -1L, | ||
| OptionalLong.empty(), | ||
| Optional.of(e)) | ||
| Errors.forException(e)); | ||
| } | ||
|
|
||
| private[server] def isListOffsetsTimestampUnsupported(timestamp: JLong, version: Short): Boolean = { | ||
|
|
@@ -1639,7 +1627,7 @@ class ReplicaManager(val config: KafkaConfig, | |
| private def processRemoteFetches(remoteFetchInfos: util.LinkedHashMap[TopicIdPartition, RemoteStorageFetchInfo], | ||
| params: FetchParams, | ||
| responseCallback: Seq[(TopicIdPartition, FetchPartitionData)] => Unit, | ||
| logReadResults: Seq[(TopicIdPartition, LogReadResult)], | ||
| logReadResults: util.LinkedHashMap[TopicIdPartition, LogReadResult], | ||
| fetchPartitionStatus: Seq[(TopicIdPartition, FetchPartitionStatus)]): Unit = { | ||
| val remoteFetchTasks = new util.HashMap[TopicIdPartition, Future[Void]] | ||
| val remoteFetchResults = new util.HashMap[TopicIdPartition, CompletableFuture[RemoteLogReadResult]] | ||
|
|
@@ -1651,8 +1639,15 @@ class ReplicaManager(val config: KafkaConfig, | |
| } | ||
|
|
||
| val remoteFetchMaxWaitMs = config.remoteLogManagerConfig.remoteFetchMaxWaitMs().toLong | ||
| val remoteFetch = new DelayedRemoteFetch(remoteFetchTasks, remoteFetchResults, remoteFetchInfos, remoteFetchMaxWaitMs, | ||
| fetchPartitionStatus, params, logReadResults, this, responseCallback) | ||
| val remoteFetch = new DelayedRemoteFetch(remoteFetchTasks, | ||
| remoteFetchResults, | ||
| remoteFetchInfos, | ||
| remoteFetchMaxWaitMs, | ||
| fetchPartitionStatus.toMap.asJava, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could initialize
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opened #20769 to address this comment. PTAL.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Didn't saw #20768 was also opened. We can merge either one.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's keep the FIFO policy and review #20768 together |
||
| params, | ||
| logReadResults, | ||
| tp => getPartitionOrException(tp), | ||
| response => responseCallback(response.asScala.toSeq)) | ||
|
|
||
| // create a list of (topic, partition) pairs to use as keys for this delayed fetch operation | ||
| val delayedFetchKeys = remoteFetchTasks.asScala.map { case (tp, _) => new TopicPartitionOperationKey(tp) }.toList | ||
|
|
@@ -1681,7 +1676,7 @@ class ReplicaManager(val config: KafkaConfig, | |
|
|
||
| var hasDivergingEpoch = false | ||
| var hasPreferredReadReplica = false | ||
| val logReadResultMap = new mutable.HashMap[TopicIdPartition, LogReadResult] | ||
| val logReadResultMap = new util.LinkedHashMap[TopicIdPartition, LogReadResult] | ||
|
|
||
| logReadResults.foreach { case (topicIdPartition, logReadResult) => | ||
| brokerTopicStats.topicStats(topicIdPartition.topicPartition.topic).totalFetchRequestRate.mark() | ||
|
|
@@ -1717,14 +1712,15 @@ class ReplicaManager(val config: KafkaConfig, | |
| // construct the fetch results from the read results | ||
| val fetchPartitionStatus = new mutable.ArrayBuffer[(TopicIdPartition, FetchPartitionStatus)] | ||
| fetchInfos.foreach { case (topicIdPartition, partitionData) => | ||
| logReadResultMap.get(topicIdPartition).foreach(logReadResult => { | ||
| val logReadResult = logReadResultMap.get(topicIdPartition) | ||
| if (logReadResult != null) { | ||
| val logOffsetMetadata = logReadResult.info.fetchOffsetMetadata | ||
| fetchPartitionStatus += (topicIdPartition -> FetchPartitionStatus(logOffsetMetadata, partitionData)) | ||
| }) | ||
| fetchPartitionStatus += (topicIdPartition -> new FetchPartitionStatus(logOffsetMetadata, partitionData)) | ||
| } | ||
| } | ||
|
|
||
| if (!remoteFetchInfos.isEmpty) { | ||
| processRemoteFetches(remoteFetchInfos, params, responseCallback, logReadResults, fetchPartitionStatus.toSeq) | ||
| processRemoteFetches(remoteFetchInfos, params, responseCallback, logReadResultMap, fetchPartitionStatus.toSeq) | ||
| } else { | ||
| // If there is not enough data to respond and there is no remote data, we will let the fetch request | ||
| // wait for new data. | ||
|
|
@@ -1812,7 +1808,7 @@ class ReplicaManager(val config: KafkaConfig, | |
| -1L, | ||
| OptionalLong.of(offsetSnapshot.lastStableOffset.messageOffset), | ||
| if (preferredReadReplica.isDefined) OptionalInt.of(preferredReadReplica.get) else OptionalInt.empty(), | ||
| Optional.empty()) | ||
| Errors.NONE) | ||
| } else { | ||
| log = partition.localLogWithEpochOrThrow(fetchInfo.currentLeaderEpoch, params.fetchOnlyLeader()) | ||
|
|
||
|
|
@@ -1836,7 +1832,7 @@ class ReplicaManager(val config: KafkaConfig, | |
| fetchTimeMs, | ||
| OptionalLong.of(readInfo.lastStableOffset), | ||
| if (preferredReadReplica.isDefined) OptionalInt.of(preferredReadReplica.get) else OptionalInt.empty(), | ||
| Optional.empty() | ||
| Errors.NONE | ||
| ) | ||
| } | ||
| } catch { | ||
|
|
@@ -1849,7 +1845,7 @@ class ReplicaManager(val config: KafkaConfig, | |
| _: ReplicaNotAvailableException | | ||
| _: KafkaStorageException | | ||
| _: InconsistentTopicIdException) => | ||
| createLogReadResult(e) | ||
| new LogReadResult(Errors.forException(e)) | ||
| case e: OffsetOutOfRangeException => | ||
| handleOffsetOutOfRangeError(tp, params, fetchInfo, adjustedMaxBytes, minOneMessage, log, fetchTimeMs, e) | ||
| case e: Throwable => | ||
|
|
@@ -1868,7 +1864,7 @@ class ReplicaManager(val config: KafkaConfig, | |
| UnifiedLog.UNKNOWN_OFFSET, | ||
| -1L, | ||
| OptionalLong.empty(), | ||
| Optional.of(e) | ||
| Errors.forException(e) | ||
| ) | ||
| } | ||
| } | ||
|
|
@@ -1949,10 +1945,10 @@ class ReplicaManager(val config: KafkaConfig, | |
| fetchInfo.logStartOffset, | ||
| fetchTimeMs, | ||
| OptionalLong.of(log.lastStableOffset), | ||
| Optional.empty[Throwable]()) | ||
| Errors.NONE) | ||
| } | ||
| } else { | ||
| createLogReadResult(exception) | ||
| new LogReadResult(Errors.forException(exception)) | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did we check that we didn't lose a useful error message by doing this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out. I checked the usage of
LogReadResultand only found calls toLogReadResult.error(), so in the previous implementation, no code would utilize the error message from the Exception.If anything is inappropriate, please feel free to correct me.