@@ -50,6 +50,7 @@ import org.apache.kafka.coordinator.transaction.{AddPartitionsToTxnConfig, Trans
50
50
import org .apache .kafka .image .{LocalReplicaChanges , MetadataImage , TopicsDelta }
51
51
import org .apache .kafka .metadata .LeaderConstants .NO_LEADER
52
52
import org .apache .kafka .metadata .MetadataCache
53
+ import org .apache .kafka .server .DelayedProduce .{ProduceMetadata , ProducePartitionStatus }
53
54
import org .apache .kafka .server .common .{DirectoryEventHandler , RequestLocal , StopPartition }
54
55
import org .apache .kafka .server .log .remote .TopicPartitionLog
55
56
import org .apache .kafka .server .config .ReplicationConfigs
@@ -61,7 +62,7 @@ import org.apache.kafka.server.share.fetch.{DelayedShareFetchKey, DelayedShareFe
61
62
import org .apache .kafka .server .storage .log .{FetchParams , FetchPartitionData }
62
63
import org .apache .kafka .server .util .timer .{SystemTimer , TimerTask }
63
64
import org .apache .kafka .server .util .{Scheduler , ShutdownableThread }
64
- import org .apache .kafka .server .{ActionQueue , DelayedActionQueue , common }
65
+ import org .apache .kafka .server .{ActionQueue , DelayedActionQueue , DelayedProduce , common }
65
66
import org .apache .kafka .storage .internals .checkpoint .{LazyOffsetCheckpoints , OffsetCheckpointFile , OffsetCheckpoints }
66
67
import org .apache .kafka .storage .internals .log .{AppendOrigin , FetchDataInfo , LeaderHwChange , LogAppendInfo , LogConfig , LogDirFailureChannel , LogOffsetMetadata , LogReadInfo , OffsetResultHolder , RecordValidationException , RemoteLogReadResult , RemoteStorageFetchInfo , UnifiedLog , VerificationGuard }
67
68
import org .apache .kafka .storage .log .metrics .BrokerTopicStats
@@ -77,6 +78,7 @@ import java.util.{Collections, Optional, OptionalInt, OptionalLong}
77
78
import java .util .function .Consumer
78
79
import scala .collection .{Map , Seq , Set , immutable , mutable }
79
80
import scala .jdk .CollectionConverters ._
81
+ import scala .jdk .FunctionConverters .enrichAsJavaConsumer
80
82
import scala .jdk .OptionConverters .{RichOption , RichOptional }
81
83
82
84
/*
@@ -734,7 +736,7 @@ class ReplicaManager(val config: KafkaConfig,
734
736
internalTopicsAllowed : Boolean ,
735
737
origin : AppendOrigin ,
736
738
entriesPerPartition : Map [TopicIdPartition , MemoryRecords ],
737
- responseCallback : Map [TopicIdPartition , PartitionResponse ] => Unit ,
739
+ responseCallback : util. Map [TopicIdPartition , PartitionResponse ] => Unit ,
738
740
delayedProduceLock : Option [Lock ] = None ,
739
741
recordValidationStatsCallback : Map [TopicIdPartition , RecordValidationStats ] => Unit = _ => (),
740
742
requestLocal : RequestLocal = RequestLocal .noCaching,
@@ -850,8 +852,8 @@ class ReplicaManager(val config: KafkaConfig,
850
852
851
853
val preAppendPartitionResponses = buildProducePartitionStatus(errorResults).map { case (k, status) => k -> status.responseStatus }
852
854
853
- def newResponseCallback (responses : Map [TopicIdPartition , PartitionResponse ]): Unit = {
854
- responseCallback(preAppendPartitionResponses ++ responses)
855
+ def newResponseCallback (responses : util. Map [TopicIdPartition , PartitionResponse ]): Unit = {
856
+ responseCallback(preAppendPartitionResponses ++ responses.asScala )
855
857
}
856
858
857
859
appendRecords(
@@ -926,7 +928,7 @@ class ReplicaManager(val config: KafkaConfig,
926
928
results : Map [TopicIdPartition , LogAppendResult ]
927
929
): Map [TopicIdPartition , ProducePartitionStatus ] = {
928
930
results.map { case (topicIdPartition, result) =>
929
- topicIdPartition -> ProducePartitionStatus (
931
+ topicIdPartition -> new ProducePartitionStatus (
930
932
result.info.lastOffset + 1 , // required offset
931
933
new PartitionResponse (
932
934
result.error,
@@ -972,12 +974,30 @@ class ReplicaManager(val config: KafkaConfig,
972
974
entriesPerPartition : Map [TopicIdPartition , MemoryRecords ],
973
975
initialAppendResults : Map [TopicIdPartition , LogAppendResult ],
974
976
initialProduceStatus : Map [TopicIdPartition , ProducePartitionStatus ],
975
- responseCallback : Map [TopicIdPartition , PartitionResponse ] => Unit ,
977
+ responseCallback : util. Map [TopicIdPartition , PartitionResponse ] => Unit ,
976
978
): Unit = {
977
979
if (delayedProduceRequestRequired(requiredAcks, entriesPerPartition, initialAppendResults)) {
978
980
// create delayed produce operation
979
- val produceMetadata = ProduceMetadata (requiredAcks, initialProduceStatus)
980
- val delayedProduce = new DelayedProduce (timeoutMs, produceMetadata, this , responseCallback, delayedProduceLock)
981
+ val produceMetadata = new ProduceMetadata (requiredAcks, initialProduceStatus.asJava)
982
+
983
+ def delegate (tp : TopicPartition , status : ProducePartitionStatus ) : Unit = {
984
+ val (hasEnough, error) = getPartitionOrError(tp) match {
985
+ case Left (err) =>
986
+ // Case A
987
+ (false , err)
988
+
989
+ case Right (partition) =>
990
+ partition.checkEnoughReplicasReachOffset(status.requiredOffset)
991
+ }
992
+
993
+ // Case B || C.1 || C.2
994
+ if (error != Errors .NONE || hasEnough) {
995
+ status.setAcksPending(false )
996
+ status.responseStatus.error = error
997
+ }
998
+ }
999
+
1000
+ val delayedProduce = new DelayedProduce (timeoutMs, produceMetadata, delegate, responseCallback.asJava, delayedProduceLock.toJava)
981
1001
982
1002
// create a list of (topic, partition) pairs to use as keys for this delayed produce operation
983
1003
val producerRequestKeys = entriesPerPartition.keys.map(new TopicPartitionOperationKey (_)).toList
@@ -989,13 +1009,13 @@ class ReplicaManager(val config: KafkaConfig,
989
1009
} else {
990
1010
// we can respond immediately
991
1011
val produceResponseStatus = initialProduceStatus.map { case (k, status) => k -> status.responseStatus }
992
- responseCallback(produceResponseStatus)
1012
+ responseCallback(produceResponseStatus.asJava )
993
1013
}
994
1014
}
995
1015
996
1016
private def sendInvalidRequiredAcksResponse (
997
1017
entries : Map [TopicIdPartition , MemoryRecords ],
998
- responseCallback : Map [TopicIdPartition , PartitionResponse ] => Unit ): Unit = {
1018
+ responseCallback : util. Map [TopicIdPartition , PartitionResponse ] => Unit ): Unit = {
999
1019
// If required.acks is outside accepted range, something is wrong with the client
1000
1020
// Just return an error and don't handle the request at all
1001
1021
val responseStatus = entries.map { case (topicIdPartition, _) =>
@@ -1006,7 +1026,7 @@ class ReplicaManager(val config: KafkaConfig,
1006
1026
LogAppendInfo .UNKNOWN_LOG_APPEND_INFO .logStartOffset
1007
1027
)
1008
1028
}
1009
- responseCallback(responseStatus)
1029
+ responseCallback(responseStatus.asJava )
1010
1030
}
1011
1031
1012
1032
/**
0 commit comments