Skip to content

Commit 89c97e1

Browse files
authored
Support 2.1 baseline consumer group apis (#2503)
1 parent 62895a8 commit 89c97e1

File tree

2 files changed

+94
-13
lines changed

2 files changed

+94
-13
lines changed

kafka/coordinator/base.py

+33-5
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ def _send_join_group_request(self):
453453
(protocol, metadata if isinstance(metadata, bytes) else metadata.encode())
454454
for protocol, metadata in self.group_protocols()
455455
]
456-
version = self._client.api_version(JoinGroupRequest, max_version=2)
456+
version = self._client.api_version(JoinGroupRequest, max_version=3)
457457
if version == 0:
458458
request = JoinGroupRequest[version](
459459
self.group_id,
@@ -493,6 +493,11 @@ def _failed_request(self, node_id, request, future, error):
493493
future.failure(error)
494494

495495
def _handle_join_group_response(self, future, send_time, response):
496+
if response.API_VERSION >= 2:
497+
self.sensors.throttle_time.record(response.throttle_time_ms)
498+
if response.throttle_time_ms > 0:
499+
log.warning("JoinGroupRequest throttled by broker (%d ms)", response.throttle_time_ms)
500+
496501
error_type = Errors.for_code(response.error_code)
497502
if error_type is Errors.NoError:
498503
log.debug("Received successful JoinGroup response for group %s: %s",
@@ -554,7 +559,7 @@ def _handle_join_group_response(self, future, send_time, response):
554559

555560
def _on_join_follower(self):
556561
# send follower's sync group with an empty assignment
557-
version = self._client.api_version(SyncGroupRequest, max_version=1)
562+
version = self._client.api_version(SyncGroupRequest, max_version=2)
558563
request = SyncGroupRequest[version](
559564
self.group_id,
560565
self._generation.generation_id,
@@ -582,7 +587,7 @@ def _on_join_leader(self, response):
582587
except Exception as e:
583588
return Future().failure(e)
584589

585-
version = self._client.api_version(SyncGroupRequest, max_version=1)
590+
version = self._client.api_version(SyncGroupRequest, max_version=2)
586591
request = SyncGroupRequest[version](
587592
self.group_id,
588593
self._generation.generation_id,
@@ -614,6 +619,11 @@ def _send_sync_group_request(self, request):
614619
return future
615620

616621
def _handle_sync_group_response(self, future, send_time, response):
622+
if response.API_VERSION >= 1:
623+
self.sensors.throttle_time.record(response.throttle_time_ms)
624+
if response.throttle_time_ms > 0:
625+
log.warning("SyncGroupRequest throttled by broker (%d ms)", response.throttle_time_ms)
626+
617627
error_type = Errors.for_code(response.error_code)
618628
if error_type is Errors.NoError:
619629
self.sensors.sync_latency.record((time.time() - send_time) * 1000)
@@ -770,7 +780,7 @@ def maybe_leave_group(self):
770780
# this is a minimal effort attempt to leave the group. we do not
771781
# attempt any resending if the request fails or times out.
772782
log.info('Leaving consumer group (%s).', self.group_id)
773-
version = self._client.api_version(LeaveGroupRequest, max_version=1)
783+
version = self._client.api_version(LeaveGroupRequest, max_version=2)
774784
request = LeaveGroupRequest[version](self.group_id, self._generation.member_id)
775785
future = self._client.send(self.coordinator_id, request)
776786
future.add_callback(self._handle_leave_group_response)
@@ -780,6 +790,11 @@ def maybe_leave_group(self):
780790
self.reset_generation()
781791

782792
def _handle_leave_group_response(self, response):
793+
if response.API_VERSION >= 1:
794+
self.sensors.throttle_time.record(response.throttle_time_ms)
795+
if response.throttle_time_ms > 0:
796+
log.warning("LeaveGroupRequest throttled by broker (%d ms)", response.throttle_time_ms)
797+
783798
error_type = Errors.for_code(response.error_code)
784799
if error_type is Errors.NoError:
785800
log.debug("LeaveGroup request for group %s returned successfully",
@@ -798,7 +813,7 @@ def _send_heartbeat_request(self):
798813
e = Errors.NodeNotReadyError(self.coordinator_id)
799814
return Future().failure(e)
800815

801-
version = self._client.api_version(HeartbeatRequest, max_version=1)
816+
version = self._client.api_version(HeartbeatRequest, max_version=2)
802817
request = HeartbeatRequest[version](self.group_id,
803818
self._generation.generation_id,
804819
self._generation.member_id)
@@ -811,6 +826,11 @@ def _send_heartbeat_request(self):
811826
return future
812827

813828
def _handle_heartbeat_response(self, future, send_time, response):
829+
if response.API_VERSION >= 1:
830+
self.sensors.throttle_time.record(response.throttle_time_ms)
831+
if response.throttle_time_ms > 0:
832+
log.warning("HeartbeatRequest throttled by broker (%d ms)", response.throttle_time_ms)
833+
814834
self.sensors.heartbeat_latency.record((time.time() - send_time) * 1000)
815835
error_type = Errors.for_code(response.error_code)
816836
if error_type is Errors.NoError:
@@ -899,6 +919,14 @@ def __init__(self, heartbeat, metrics, prefix, tags=None):
899919
tags), AnonMeasurable(
900920
lambda _, now: (now / 1000) - self.heartbeat.last_send))
901921

922+
self.throttle_time = metrics.sensor('throttle-time')
923+
self.throttle_time.add(metrics.metric_name(
924+
'throttle-time-avg', self.metric_group_name,
925+
'The average throttle time in ms'), Avg())
926+
self.throttle_time.add(metrics.metric_name(
927+
'throttle-time-max', self.metric_group_name,
928+
'The maximum throttle time in ms'), Max())
929+
902930

903931
class HeartbeatThread(threading.Thread):
904932
def __init__(self, coordinator):

kafka/protocol/group.py

+61-8
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ class JoinGroupResponse_v2(Response):
4242
)
4343

4444

45+
class JoinGroupResponse_v3(Response):
46+
API_KEY = 11
47+
API_VERSION = 3
48+
SCHEMA = JoinGroupResponse_v2.SCHEMA
49+
50+
4551
class JoinGroupRequest_v0(Request):
4652
API_KEY = 11
4753
API_VERSION = 0
@@ -83,11 +89,19 @@ class JoinGroupRequest_v2(Request):
8389
UNKNOWN_MEMBER_ID = ''
8490

8591

92+
class JoinGroupRequest_v3(Request):
93+
API_KEY = 11
94+
API_VERSION = 3
95+
RESPONSE_TYPE = JoinGroupResponse_v3
96+
SCHEMA = JoinGroupRequest_v2.SCHEMA
97+
UNKNOWN_MEMBER_ID = ''
98+
99+
86100
JoinGroupRequest = [
87-
JoinGroupRequest_v0, JoinGroupRequest_v1, JoinGroupRequest_v2
101+
JoinGroupRequest_v0, JoinGroupRequest_v1, JoinGroupRequest_v2, JoinGroupRequest_v3
88102
]
89103
JoinGroupResponse = [
90-
JoinGroupResponse_v0, JoinGroupResponse_v1, JoinGroupResponse_v2
104+
JoinGroupResponse_v0, JoinGroupResponse_v1, JoinGroupResponse_v2, JoinGroupResponse_v3
91105
]
92106

93107

@@ -118,6 +132,12 @@ class SyncGroupResponse_v1(Response):
118132
)
119133

120134

135+
class SyncGroupResponse_v2(Response):
136+
API_KEY = 14
137+
API_VERSION = 2
138+
SCHEMA = SyncGroupResponse_v1.SCHEMA
139+
140+
121141
class SyncGroupRequest_v0(Request):
122142
API_KEY = 14
123143
API_VERSION = 0
@@ -139,8 +159,15 @@ class SyncGroupRequest_v1(Request):
139159
SCHEMA = SyncGroupRequest_v0.SCHEMA
140160

141161

142-
SyncGroupRequest = [SyncGroupRequest_v0, SyncGroupRequest_v1]
143-
SyncGroupResponse = [SyncGroupResponse_v0, SyncGroupResponse_v1]
162+
class SyncGroupRequest_v2(Request):
163+
API_KEY = 14
164+
API_VERSION = 2
165+
RESPONSE_TYPE = SyncGroupResponse_v2
166+
SCHEMA = SyncGroupRequest_v1.SCHEMA
167+
168+
169+
SyncGroupRequest = [SyncGroupRequest_v0, SyncGroupRequest_v1, SyncGroupRequest_v2]
170+
SyncGroupResponse = [SyncGroupResponse_v0, SyncGroupResponse_v1, SyncGroupResponse_v2]
144171

145172

146173
class MemberAssignment(Struct):
@@ -170,6 +197,12 @@ class HeartbeatResponse_v1(Response):
170197
)
171198

172199

200+
class HeartbeatResponse_v2(Response):
201+
API_KEY = 12
202+
API_VERSION = 2
203+
SCHEMA = HeartbeatResponse_v1.SCHEMA
204+
205+
173206
class HeartbeatRequest_v0(Request):
174207
API_KEY = 12
175208
API_VERSION = 0
@@ -188,8 +221,15 @@ class HeartbeatRequest_v1(Request):
188221
SCHEMA = HeartbeatRequest_v0.SCHEMA
189222

190223

191-
HeartbeatRequest = [HeartbeatRequest_v0, HeartbeatRequest_v1]
192-
HeartbeatResponse = [HeartbeatResponse_v0, HeartbeatResponse_v1]
224+
class HeartbeatRequest_v2(Request):
225+
API_KEY = 12
226+
API_VERSION = 2
227+
RESPONSE_TYPE = HeartbeatResponse_v2
228+
SCHEMA = HeartbeatRequest_v1.SCHEMA
229+
230+
231+
HeartbeatRequest = [HeartbeatRequest_v0, HeartbeatRequest_v1, HeartbeatRequest_v2]
232+
HeartbeatResponse = [HeartbeatResponse_v0, HeartbeatResponse_v1, HeartbeatResponse_v2]
193233

194234

195235
class LeaveGroupResponse_v0(Response):
@@ -209,6 +249,12 @@ class LeaveGroupResponse_v1(Response):
209249
)
210250

211251

252+
class LeaveGroupResponse_v2(Response):
253+
API_KEY = 13
254+
API_VERSION = 2
255+
SCHEMA = LeaveGroupResponse_v1.SCHEMA
256+
257+
212258
class LeaveGroupRequest_v0(Request):
213259
API_KEY = 13
214260
API_VERSION = 0
@@ -226,5 +272,12 @@ class LeaveGroupRequest_v1(Request):
226272
SCHEMA = LeaveGroupRequest_v0.SCHEMA
227273

228274

229-
LeaveGroupRequest = [LeaveGroupRequest_v0, LeaveGroupRequest_v1]
230-
LeaveGroupResponse = [LeaveGroupResponse_v0, LeaveGroupResponse_v1]
275+
class LeaveGroupRequest_v2(Request):
276+
API_KEY = 13
277+
API_VERSION = 2
278+
RESPONSE_TYPE = LeaveGroupResponse_v2
279+
SCHEMA = LeaveGroupRequest_v1.SCHEMA
280+
281+
282+
LeaveGroupRequest = [LeaveGroupRequest_v0, LeaveGroupRequest_v1, LeaveGroupRequest_v2]
283+
LeaveGroupResponse = [LeaveGroupResponse_v0, LeaveGroupResponse_v1, LeaveGroupResponse_v2]

0 commit comments

Comments
 (0)