@@ -114,6 +114,7 @@ def __init__(self, client, subscriptions, metrics, **configs):
114
114
self ._sensors = FetchManagerMetrics (metrics , self .config ['metric_group_prefix' ])
115
115
self ._isolation_level = READ_UNCOMMITTED
116
116
self ._session_handlers = {}
117
+ self ._nodes_with_pending_fetch_requests = set ()
117
118
118
119
def send_fetches (self ):
119
120
"""Send FetchRequests for all assigned partitions that do not already have
@@ -124,12 +125,12 @@ def send_fetches(self):
124
125
"""
125
126
futures = []
126
127
for node_id , (request , fetch_offsets ) in six .iteritems (self ._create_fetch_requests ()):
127
- if self . _client . ready ( node_id ):
128
- log . debug ( "Sending FetchRequest to node %s" , node_id )
129
- future = self ._client .send (node_id , request , wakeup = False )
130
- future .add_callback (self ._handle_fetch_response , node_id , fetch_offsets , time .time ())
131
- future .add_errback (self ._handle_fetch_error , node_id )
132
- futures .append (future )
128
+ log . debug ( "Sending FetchRequest to node %s" , node_id )
129
+ self . _nodes_with_pending_fetch_requests . add ( node_id )
130
+ future = self ._client .send (node_id , request , wakeup = False )
131
+ future .add_callback (self ._handle_fetch_response , node_id , fetch_offsets , time .time ())
132
+ future .add_errback (self ._handle_fetch_error , node_id )
133
+ futures .append (future )
133
134
self ._fetch_futures .extend (futures )
134
135
self ._clean_done_fetch_futures ()
135
136
return futures
@@ -593,8 +594,20 @@ def _create_fetch_requests(self):
593
594
" Requesting metadata update" , partition )
594
595
self ._client .cluster .request_update ()
595
596
596
- elif self ._client .in_flight_request_count (node_id ) > 0 :
597
- log .log (0 , "Skipping fetch for partition %s because there is an inflight request to node %s" ,
597
+ elif not self ._client .connected (node_id ) and self ._client .connection_delay (node_id ) > 0 :
598
+ # If we try to send during the reconnect backoff window, then the request is just
599
+ # going to be failed anyway before being sent, so skip the send for now
600
+ log .log (0 , "Skipping fetch for partition %s because node %s is awaiting reconnect backoff" ,
601
+ partition , node_id )
602
+
603
+ elif self ._client .throttle_delay (node_id ) > 0 :
604
+ # If we try to send while throttled, then the request is just
605
+ # going to be failed anyway before being sent, so skip the send for now
606
+ log .log (0 , "Skipping fetch for partition %s because node %s is throttled" ,
607
+ partition , node_id )
608
+
609
+ elif node_id in self ._nodes_with_pending_fetch_requests :
610
+ log .log (0 , "Skipping fetch for partition %s because there is a pending fetch request to node %s" ,
598
611
partition , node_id )
599
612
continue
600
613
@@ -707,12 +720,14 @@ def _handle_fetch_response(self, node_id, fetch_offsets, send_time, response):
707
720
self ._completed_fetches .append (completed_fetch )
708
721
709
722
self ._sensors .fetch_latency .record ((time .time () - send_time ) * 1000 )
723
+ self ._nodes_with_pending_fetch_requests .remove (node_id )
710
724
711
725
def _handle_fetch_error (self , node_id , exception ):
712
726
level = logging .INFO if isinstance (exception , Errors .Cancelled ) else logging .ERROR
713
727
log .log (level , 'Fetch to node %s failed: %s' , node_id , exception )
714
728
if node_id in self ._session_handlers :
715
729
self ._session_handlers [node_id ].handle_error (exception )
730
+ self ._nodes_with_pending_fetch_requests .remove (node_id )
716
731
717
732
def _parse_fetched_data (self , completed_fetch ):
718
733
tp = completed_fetch .topic_partition
0 commit comments