@@ -201,45 +201,56 @@ def __exit__(self, *unused_args):
201201 self .stop ()
202202
203203 def start (self ):
204- try :
205- process , endpoint = self .start_process ()
206- wait_secs = .1
207- channel_options = [
208- ("grpc.max_receive_message_length" , - 1 ),
209- ("grpc.max_send_message_length" , - 1 ),
210- # Default: 20000ms (20s), increased to 10 minutes for stability
211- ("grpc.keepalive_timeout_ms" , 600_000 ),
212- # Default: 2, set to 0 to allow unlimited pings without data
213- ("grpc.http2.max_pings_without_data" , 0 ),
214- # Default: False, set to True to allow keepalive pings when no calls
215- ("grpc.keepalive_permit_without_calls" , True ),
216- # Default: 2, set to 0 to allow unlimited ping strikes
217- ("grpc.http2.max_ping_strikes" , 0 ),
218- # Default: 0 (disabled), enable socket reuse for better handling
219- ("grpc.so_reuseport" , 1 ),
220- ]
221- self ._grpc_channel = grpc .insecure_channel (
222- endpoint , options = channel_options )
223- channel_ready = grpc .channel_ready_future (self ._grpc_channel )
224- while True :
225- if process is not None and process .poll () is not None :
226- _LOGGER .error ("Failed to start job service with %s" , process .args )
227- raise RuntimeError (
228- 'Service failed to start up with error %s' % process .poll ())
229- try :
230- channel_ready .result (timeout = wait_secs )
231- break
232- except (grpc .FutureTimeoutError , grpc .RpcError ):
233- wait_secs *= 1.2
234- logging .log (
235- logging .WARNING if wait_secs > 1 else logging .DEBUG ,
236- 'Waiting for grpc channel to be ready at %s.' ,
237- endpoint )
238- return self ._stub_class (self ._grpc_channel )
239- except : # pylint: disable=bare-except
240- _LOGGER .exception ("Error bringing up service" )
241- self .stop_force ()
242- raise
204+ max_retries = 3
205+ for attempt in range (max_retries ):
206+ try :
207+ process , endpoint = self .start_process ()
208+ wait_secs = .1
209+ channel_options = [
210+ ("grpc.max_receive_message_length" , - 1 ),
211+ ("grpc.max_send_message_length" , - 1 ),
212+ # Default: 20000ms (20s), increased to 10 minutes for stability
213+ ("grpc.keepalive_timeout_ms" , 600_000 ),
214+ # Default: 2, set to 0 to allow unlimited pings without data
215+ ("grpc.http2.max_pings_without_data" , 0 ),
216+ # Default: False, set to True to allow keepalive pings when no calls
217+ ("grpc.keepalive_permit_without_calls" , True ),
218+ # Default: 2, set to 0 to allow unlimited ping strikes
219+ ("grpc.http2.max_ping_strikes" , 0 ),
220+ # Default: 0 (disabled), enable socket reuse for better handling
221+ ("grpc.so_reuseport" , 1 ),
222+ ]
223+ self ._grpc_channel = grpc .insecure_channel (
224+ endpoint , options = channel_options )
225+ channel_ready = grpc .channel_ready_future (self ._grpc_channel )
226+ while True :
227+ if process is not None and process .poll () is not None :
228+ _LOGGER .error ("Failed to start job service with %s" , process .args )
229+ raise RuntimeError (
230+ 'Service failed to start up with error %s' % process .poll ())
231+ try :
232+ channel_ready .result (timeout = wait_secs )
233+ break
234+ except (grpc .FutureTimeoutError , grpc .RpcError ):
235+ wait_secs *= 1.2
236+ logging .log (
237+ logging .WARNING if wait_secs > 1 else logging .DEBUG ,
238+ 'Waiting for grpc channel to be ready at %s.' ,
239+ endpoint )
240+ return self ._stub_class (self ._grpc_channel )
241+ except Exception as e :
242+ _LOGGER .warning (
243+ "Error bringing up service (attempt %d of %d): %s" ,
244+ attempt + 1 ,
245+ max_retries ,
246+ e )
247+ self .stop_force ()
248+ if attempt == max_retries - 1 :
249+ raise
250+ time .sleep (1 )
251+ except : # pylint: disable=bare-except
252+ self .stop_force ()
253+ raise
243254
244255 def start_process (self ):
245256 if self ._owner_id is not None :
0 commit comments