@@ -662,20 +662,49 @@ def unschedule(self, task):
662
662
self ._delayed_tasks .remove (task )
663
663
664
664
def check_version (self , node_id = None , timeout = 2 , strict = False ):
665
- """Attempt to guess the broker version"""
666
- if node_id is None :
667
- node_id = self .least_loaded_node ()
668
- if node_id is None :
665
+ """Attempt to guess a broker version
666
+
667
+ Note: it is possible that this method blocks longer than the
668
+ specified timeout. This can happen if the entire cluster
669
+ is down and the client enters a bootstrap backoff sleep.
670
+ This is only possible if node_id is None.
671
+
672
+ Returns: version str, i.e. '0.10', '0.9', '0.8.2', '0.8.1', '0.8.0'
673
+
674
+ Raises:
675
+ NodeNotReadyError (if node_id is provided)
676
+ NoBrokersAvailable (if node_id is None)
677
+ UnrecognizedBrokerVersion: please file bug if seen!
678
+ AssertionError (if strict=True): please file bug if seen!
679
+ """
680
+ end = time .time () + timeout
681
+ while time .time () < end :
682
+
683
+ # It is possible that least_loaded_node falls back to bootstrap,
684
+ # which can block for an increasing backoff period
685
+ try_node = node_id or self .least_loaded_node ()
686
+ if try_node is None :
669
687
raise Errors .NoBrokersAvailable ()
688
+ self ._maybe_connect (try_node )
689
+ conn = self ._conns [try_node ]
670
690
671
- # We will be intentionally causing socket failures
672
- # and should not trigger metadata refresh
673
- self ._refresh_on_disconnects = False
674
- self ._maybe_connect (node_id )
675
- conn = self ._conns [node_id ]
676
- version = conn .check_version ()
677
- self ._refresh_on_disconnects = True
678
- return version
691
+ # We will intentionally cause socket failures
692
+ # These should not trigger metadata refresh
693
+ self ._refresh_on_disconnects = False
694
+ try :
695
+ remaining = end - time .time ()
696
+ version = conn .check_version (timeout = remaining , strict = strict )
697
+ return version
698
+ except Errors .NodeNotReadyError :
699
+ # Only raise to user if this is a node-specific request
700
+ if node_id is not None :
701
+ raise
702
+ finally :
703
+ self ._refresh_on_disconnects = True
704
+
705
+ # Timeout
706
+ else :
707
+ raise Errors .NoBrokersAvailable ()
679
708
680
709
def wakeup (self ):
681
710
if self ._wake_w .send (b'x' ) != 1 :
0 commit comments