@@ -973,49 +973,26 @@ def _get_leader_for_partitions(self, partitions, timeout_ms=None):
973
973
:return: Dictionary with ``{leader_id -> {partitions}}``
974
974
"""
975
975
timeout_ms = self ._validate_timeout (timeout_ms )
976
- version = self ._matching_api_version (MetadataRequest )
977
976
978
977
partitions = set (partitions )
979
- topics = set ()
980
-
981
- for topic_partition in partitions :
982
- topics .add (topic_partition .topic )
983
-
984
- request = MetadataRequest [version ](
985
- topics = list (topics ),
986
- allow_auto_topic_creation = False
987
- )
988
-
989
- future = self ._send_request_to_node (self ._client .least_loaded_node (), request )
990
-
991
- self ._wait_for_futures ([future ])
992
- response = future .value
993
-
994
- version = self ._matching_api_version (DeleteRecordsRequest )
978
+ topics = set (tp .topic for tp in partitions )
995
979
996
- PARTITIONS_INFO = 3
997
- NAME = 1
998
- PARTITION_INDEX = 1
999
- LEADER = 2
980
+ response = self ._get_cluster_metadata (topics = topics ).to_object ()
1000
981
1001
- # We want to make as few requests as possible
1002
- # If a single node serves as a partition leader for multiple partitions (and/or
1003
- # topics), we can send all of those in a single request.
1004
- # For that we store {leader -> {topic1 -> [p0, p1], topic2 -> [p0, p1]}}
1005
982
leader2partitions = defaultdict (list )
1006
983
valid_partitions = set ()
1007
- for topic in response .topics :
1008
- for partition in topic [ PARTITIONS_INFO ] :
1009
- t2p = TopicPartition (topic = topic [NAME ], partition = partition [PARTITION_INDEX ])
984
+ for topic in response .get ( " topics" , ()) :
985
+ for partition in topic . get ( "partitions" , ()) :
986
+ t2p = TopicPartition (topic = topic ["topic" ], partition = partition ["partition" ])
1010
987
if t2p in partitions :
1011
- leader2partitions [partition [LEADER ]].append (t2p )
988
+ leader2partitions [partition ["leader" ]].append (t2p )
1012
989
valid_partitions .add (t2p )
1013
990
1014
991
if len (partitions ) != len (valid_partitions ):
1015
992
unknown = set (partitions ) - valid_partitions
1016
993
raise UnknownTopicOrPartitionError (
1017
- "The following partitions are not known: %s" % ", "
1018
- .join (str (x ) for x in unknown )
994
+ "The following partitions are not known: %s"
995
+ % ", " .join (str (x ) for x in unknown )
1019
996
)
1020
997
1021
998
return leader2partitions
@@ -1029,14 +1006,20 @@ def delete_records(self, records_to_delete, timeout_ms=None, partition_leader_id
1029
1006
config.
1030
1007
:param partition_leader_id: ``str``: If specified, all deletion requests will be sent to
1031
1008
this node. No check is performed verifying that this is indeed the leader for all
1032
- listed partitions, use with caution.
1009
+ listed partitions: use with caution.
1033
1010
1034
- :return: List of DeleteRecordsResponse
1011
+ :return: Dictionary {topicPartition -> metadata}, where metadata is returned by the broker.
1012
+ See DeleteRecordsResponse for possible fields. error_code for all partitions is
1013
+ guaranteed to be zero, otherwise an exception is raised.
1035
1014
"""
1036
1015
timeout_ms = self ._validate_timeout (timeout_ms )
1037
1016
responses = []
1038
1017
version = self ._matching_api_version (DeleteRecordsRequest )
1039
1018
1019
+ # We want to make as few requests as possible
1020
+ # If a single node serves as a partition leader for multiple partitions (and/or
1021
+ # topics), we can send all of those in a single request.
1022
+ # For that we store {leader -> {partitions for leader}}, and do 1 request per leader
1040
1023
if partition_leader_id is None :
1041
1024
leader2partitions = self ._get_leader_for_partitions (
1042
1025
set (records_to_delete ), timeout_ms
@@ -1059,27 +1042,35 @@ def delete_records(self, records_to_delete, timeout_ms=None, partition_leader_id
1059
1042
future = self ._send_request_to_node (leader , request )
1060
1043
self ._wait_for_futures ([future ])
1061
1044
1062
- response = future .value
1063
- responses .append (response )
1045
+ responses .append (future .value .to_object ())
1064
1046
1047
+ partition2result = {}
1065
1048
partition2error = {}
1066
1049
for response in responses :
1067
- for topic in getattr (response , 'topics' , ()):
1068
- for partition in getattr (topic , 'partitions' , ()):
1069
- if getattr (partition , 'error_code' , 0 ) != 0 :
1070
- tp = TopicPartition (topic , partition ['partition_index' ])
1071
- partition2error [tp ] = partition ['error_code' ]
1050
+ for topic in response ["topics" ]:
1051
+ for partition in topic ["partitions" ]:
1052
+ tp = TopicPartition (topic ["name" ], partition ["partition_index" ])
1053
+ partition2result [tp ] = partition
1054
+ if partition ["error_code" ] != 0 :
1055
+ partition2error [tp ] = partition ["error_code" ]
1072
1056
1073
1057
if partition2error :
1074
1058
if len (partition2error ) == 1 :
1075
- raise Errors .for_code (partition2error [0 ])()
1059
+ key , error = next (iter (partition2error .items ()))
1060
+ raise Errors .for_code (error )(
1061
+ "Error deleting records from topic %s partition %s" % (key .topic , key .partition )
1062
+ )
1076
1063
else :
1077
1064
raise Errors .BrokerResponseError (
1078
- "The following errors occured when trying to delete records: "
1079
- ", " .join ("%s: %s" % (partition , error ) for partition , error in partition2error .items ())
1065
+ "The following errors occured when trying to delete records: " +
1066
+ ", " .join (
1067
+ "%s(partition=%d): %s" %
1068
+ (partition .topic , partition .partition , Errors .for_code (error ).__name__ )
1069
+ for partition , error in partition2error .items ()
1070
+ )
1080
1071
)
1081
1072
1082
- return responses
1073
+ return partition2result
1083
1074
1084
1075
# create delegation token protocol not yet implemented
1085
1076
# Note: send the request to the least_loaded_node()
0 commit comments