apoorvmittal10 commented on code in PR #16456: URL: https://github.com/apache/kafka/pull/16456#discussion_r1664122712
########## core/src/main/java/kafka/server/share/SharePartitionManager.java: ########## @@ -427,6 +427,26 @@ public List<TopicIdPartition> cachedTopicIdPartitionsInShareSession(String group return cachedTopicIdPartitions; } + /** + * The acknowledgeShareSessionCacheUpdate method is used to update the share session cache before acknowledgements are handled + * either as part of shareFetch request or shareAcknowledge request + * @param groupId The group id in the request. + * @param memberId The member id of the client in the request. + * @param reqEpoch The request epoch. + */ + public void acknowledgeShareSessionCacheUpdate(String groupId, Uuid memberId, int reqEpoch) { Review Comment: Is this method being used anywhere now? ########## core/src/main/scala/kafka/server/KafkaApis.scala: ########## @@ -3956,11 +3961,482 @@ class KafkaApis(val requestChannel: RequestChannel, } } + /** + * Handle a shareFetch request + */ def handleShareFetchRequest(request: RequestChannel.Request): Unit = { val shareFetchRequest = request.body[ShareFetchRequest] - // TODO: Implement the ShareFetchRequest handling - requestHelper.sendMaybeThrottle(request, shareFetchRequest.getErrorResponse(Errors.UNSUPPORTED_VERSION.exception)) - CompletableFuture.completedFuture[Unit](()) + + if (!config.isNewGroupCoordinatorEnabled) { + // The API is not supported by the "old" group coordinator (the default). If the + // new one is not enabled, we fail directly here. + requestHelper.sendMaybeThrottle(request, shareFetchRequest.getErrorResponse(Errors.UNSUPPORTED_VERSION.exception)) + CompletableFuture.completedFuture[Unit](()) + return + } else if (!config.isShareGroupEnabled) { + // The API is not supported when the "share" rebalance protocol has not been set explicitly + requestHelper.sendMaybeThrottle(request, shareFetchRequest.getErrorResponse(Errors.UNSUPPORTED_VERSION.exception)) + CompletableFuture.completedFuture[Unit](()) + return + } + val topicNames = metadataCache.topicIdsToNames() + val sharePartitionManager : SharePartitionManager = sharePartitionManagerOption match { + case Some(manager) => manager + case None => throw new IllegalStateException("ShareFetchRequest received but SharePartitionManager is not initialized") + } + + val groupId = shareFetchRequest.data.groupId + val clientId = request.header.clientId + val memberId = shareFetchRequest.data().memberId() + val shareSessionEpoch = shareFetchRequest.data().shareSessionEpoch() + + val shareFetchData = shareFetchRequest.shareFetchData(topicNames) + val forgottenTopics = shareFetchRequest.forgottenTopics(topicNames) + var cachedTopicPartitions : util.List[TopicIdPartition] = null + + if (shareSessionEpoch == ShareFetchMetadata.FINAL_EPOCH) { + try { + cachedTopicPartitions = sharePartitionManager.cachedTopicIdPartitionsInShareSession(groupId, Uuid.fromString(memberId)) + } catch { + // Exception handling is needed when this value is being utilized on receiving FINAL_EPOCH. + case _: ShareSessionNotFoundException => cachedTopicPartitions = null + } + } + + def isAcknowledgeDataPresentInFetchRequest() : Boolean = { + var isAcknowledgeDataPresent = false + shareFetchRequest.data().topics().forEach ( topic => { + breakable{ + topic.partitions().forEach ( partition => { + if (partition.acknowledgementBatches() != null && !partition.acknowledgementBatches().isEmpty) { + isAcknowledgeDataPresent = true + break() + } else { + isAcknowledgeDataPresent = false + } + }) + } + }) + isAcknowledgeDataPresent + } + + val isAcknowledgeDataPresent = isAcknowledgeDataPresentInFetchRequest() + var shareFetchResponse : ShareFetchResponse = null + // Variable to store any error thrown while the handling piggybacked acknowledgements + var acknowledgeError : Errors = Errors.NONE + // Variable to store the topic partition wise result of piggybacked acknowledgements + var acknowledgeResult = mutable.Map[TopicIdPartition, ShareAcknowledgeResponseData.PartitionData]() + + def isInvalidShareFetchRequest() : Boolean = { + // The Initial Share Fetch Request should not Acknowledge any data + if (shareSessionEpoch == ShareFetchMetadata.INITIAL_EPOCH && isAcknowledgeDataPresent) { + return true + } + false + } + + val newReqMetadata : ShareFetchMetadata = new ShareFetchMetadata(Uuid.fromString(memberId), shareSessionEpoch) + var shareFetchContext : ShareFetchContext = null + try { + // Creating the shareFetchContext for Share Session Handling + shareFetchContext = sharePartitionManager.newContext(groupId, shareFetchData, forgottenTopics, newReqMetadata) + } catch { + case e: Exception => shareFetchResponse = shareFetchRequest.getErrorResponse(AbstractResponse.DEFAULT_THROTTLE_TIME, e) match { + case response: ShareFetchResponse => response + case _ => null Review Comment: My concern is on below code, should we complete the API call if `errorResponse` is constructed? ``` case e: Exception => shareFetchResponse = shareFetchRequest.getErrorResponse(AbstractResponse.DEFAULT_THROTTLE_TIME, e) match { case response: ShareFetchResponse => response case _ => null -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: jira-unsubscr...@kafka.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org