1616from kafka .metrics .stats import Avg , Count , Max , Rate
1717from kafka .protocol .find_coordinator import FindCoordinatorRequest
1818from kafka .protocol .group import HeartbeatRequest , JoinGroupRequest , LeaveGroupRequest , SyncGroupRequest , DEFAULT_GENERATION_ID , UNKNOWN_MEMBER_ID
19- from kafka .util import timeout_ms_fn
19+ from kafka .util import Timer
2020
2121log = logging .getLogger ('kafka.coordinator' )
2222
@@ -256,9 +256,9 @@ def ensure_coordinator_ready(self, timeout_ms=None):
256256 timeout_ms (numeric, optional): Maximum number of milliseconds to
257257 block waiting to find coordinator. Default: None.
258258
259- Raises: KafkaTimeoutError if timeout_ms is not None
259+ Returns: True is coordinator found before timeout_ms, else False
260260 """
261- inner_timeout_ms = timeout_ms_fn (timeout_ms , 'Timeout attempting to find group coordinator' )
261+ timer = Timer (timeout_ms )
262262 with self ._client ._lock , self ._lock :
263263 while self .coordinator_unknown ():
264264
@@ -272,27 +272,37 @@ def ensure_coordinator_ready(self, timeout_ms=None):
272272 else :
273273 self .coordinator_id = maybe_coordinator_id
274274 self ._client .maybe_connect (self .coordinator_id )
275- continue
275+ if timer .expired :
276+ return False
277+ else :
278+ continue
276279 else :
277280 future = self .lookup_coordinator ()
278281
279- self ._client .poll (future = future , timeout_ms = inner_timeout_ms () )
282+ self ._client .poll (future = future , timeout_ms = timer . timeout_ms )
280283
281284 if not future .is_done :
282- raise Errors . KafkaTimeoutError ()
285+ return False
283286
284287 if future .failed ():
285288 if future .retriable ():
286289 if getattr (future .exception , 'invalid_metadata' , False ):
287290 log .debug ('Requesting metadata for group coordinator request: %s' , future .exception )
288291 metadata_update = self ._client .cluster .request_update ()
289- self ._client .poll (future = metadata_update , timeout_ms = inner_timeout_ms () )
292+ self ._client .poll (future = metadata_update , timeout_ms = timer . timeout_ms )
290293 if not metadata_update .is_done :
291- raise Errors . KafkaTimeoutError ()
294+ return False
292295 else :
293- time .sleep (inner_timeout_ms (self .config ['retry_backoff_ms' ]) / 1000 )
296+ if timeout_ms is None or timer .timeout_ms > self .config ['retry_backoff_ms' ]:
297+ time .sleep (self .config ['retry_backoff_ms' ] / 1000 )
298+ else :
299+ time .sleep (timer .timeout_ms / 1000 )
294300 else :
295301 raise future .exception # pylint: disable-msg=raising-bad-type
302+ if timer .expired :
303+ return False
304+ else :
305+ return True
296306
297307 def _reset_find_coordinator_future (self , result ):
298308 self ._find_coordinator_future = None
@@ -407,21 +417,23 @@ def ensure_active_group(self, timeout_ms=None):
407417 timeout_ms (numeric, optional): Maximum number of milliseconds to
408418 block waiting to join group. Default: None.
409419
410- Raises: KafkaTimeoutError if timeout_ms is not None
420+ Returns: True if group initialized before timeout_ms, else False
411421 """
412422 if self .config ['api_version' ] < (0 , 9 ):
413423 raise Errors .UnsupportedVersionError ('Group Coordinator APIs require 0.9+ broker' )
414- inner_timeout_ms = timeout_ms_fn (timeout_ms , 'Timeout attempting to join consumer group' )
415- self .ensure_coordinator_ready (timeout_ms = inner_timeout_ms ())
424+ timer = Timer (timeout_ms )
425+ if not self .ensure_coordinator_ready (timeout_ms = timer .timeout_ms ):
426+ return False
416427 self ._start_heartbeat_thread ()
417- self .join_group (timeout_ms = inner_timeout_ms () )
428+ return self .join_group (timeout_ms = timer . timeout_ms )
418429
419430 def join_group (self , timeout_ms = None ):
420431 if self .config ['api_version' ] < (0 , 9 ):
421432 raise Errors .UnsupportedVersionError ('Group Coordinator APIs require 0.9+ broker' )
422- inner_timeout_ms = timeout_ms_fn (timeout_ms , 'Timeout attempting to join consumer group' )
433+ timer = Timer (timeout_ms )
423434 while self .need_rejoin ():
424- self .ensure_coordinator_ready (timeout_ms = inner_timeout_ms ())
435+ if not self .ensure_coordinator_ready (timeout_ms = timer .timeout_ms ):
436+ return False
425437
426438 # call on_join_prepare if needed. We set a flag
427439 # to make sure that we do not call it a second
@@ -434,7 +446,7 @@ def join_group(self, timeout_ms=None):
434446 if not self .rejoining :
435447 self ._on_join_prepare (self ._generation .generation_id ,
436448 self ._generation .member_id ,
437- timeout_ms = inner_timeout_ms () )
449+ timeout_ms = timer . timeout_ms )
438450 self .rejoining = True
439451
440452 # fence off the heartbeat thread explicitly so that it cannot
@@ -449,16 +461,19 @@ def join_group(self, timeout_ms=None):
449461 while not self .coordinator_unknown ():
450462 if not self ._client .in_flight_request_count (self .coordinator_id ):
451463 break
452- self ._client .poll (timeout_ms = inner_timeout_ms (200 ))
464+ poll_timeout_ms = 200 if timer .timeout_ms is None or timer .timeout_ms > 200 else timer .timeout_ms
465+ self ._client .poll (timeout_ms = poll_timeout_ms )
466+ if timer .expired :
467+ return False
453468 else :
454469 continue
455470
456471 future = self ._initiate_join_group ()
457- self ._client .poll (future = future , timeout_ms = inner_timeout_ms () )
472+ self ._client .poll (future = future , timeout_ms = timer . timeout_ms )
458473 if future .is_done :
459474 self ._reset_join_group_future ()
460475 else :
461- raise Errors . KafkaTimeoutError ()
476+ return False
462477
463478 if future .succeeded ():
464479 self .rejoining = False
@@ -467,6 +482,7 @@ def join_group(self, timeout_ms=None):
467482 self ._generation .member_id ,
468483 self ._generation .protocol ,
469484 future .value )
485+ return True
470486 else :
471487 exception = future .exception
472488 if isinstance (exception , (Errors .UnknownMemberIdError ,
@@ -476,7 +492,13 @@ def join_group(self, timeout_ms=None):
476492 continue
477493 elif not future .retriable ():
478494 raise exception # pylint: disable-msg=raising-bad-type
479- time .sleep (inner_timeout_ms (self .config ['retry_backoff_ms' ]) / 1000 )
495+ elif timer .expired :
496+ return False
497+ else :
498+ if timer .timeout_ms is None or timer .timeout_ms > self .config ['retry_backoff_ms' ]:
499+ time .sleep (self .config ['retry_backoff_ms' ] / 1000 )
500+ else :
501+ time .sleep (timer .timeout_ms / 1000 )
480502
481503 def _send_join_group_request (self ):
482504 """Join the group and return the assignment for the next generation.
0 commit comments