@@ -186,45 +186,53 @@ def __exit__(self, *unused_args):
186186 self .stop ()
187187
188188 def start (self ):
189- try :
190- process , endpoint = self .start_process ()
191- wait_secs = .1
192- channel_options = [
193- ("grpc.max_receive_message_length" , - 1 ),
194- ("grpc.max_send_message_length" , - 1 ),
195- # Default: 20000ms (20s), increased to 10 minutes for stability
196- ("grpc.keepalive_timeout_ms" , 600_000 ),
197- # Default: 2, set to 0 to allow unlimited pings without data
198- ("grpc.http2.max_pings_without_data" , 0 ),
199- # Default: False, set to True to allow keepalive pings when no calls
200- ("grpc.keepalive_permit_without_calls" , True ),
201- # Default: 2, set to 0 to allow unlimited ping strikes
202- ("grpc.http2.max_ping_strikes" , 0 ),
203- # Default: 0 (disabled), enable socket reuse for better handling
204- ("grpc.so_reuseport" , 1 ),
205- ]
206- self ._grpc_channel = grpc .insecure_channel (
207- endpoint , options = channel_options )
208- channel_ready = grpc .channel_ready_future (self ._grpc_channel )
209- while True :
210- if process is not None and process .poll () is not None :
211- _LOGGER .error ("Started job service with %s" , process .args )
212- raise RuntimeError (
213- 'Service failed to start up with error %s' % process .poll ())
214- try :
215- channel_ready .result (timeout = wait_secs )
216- break
217- except (grpc .FutureTimeoutError , grpc .RpcError ):
218- wait_secs *= 1.2
219- logging .log (
220- logging .WARNING if wait_secs > 1 else logging .DEBUG ,
221- 'Waiting for grpc channel to be ready at %s.' ,
222- endpoint )
223- return self ._stub_class (self ._grpc_channel )
224- except : # pylint: disable=bare-except
225- _LOGGER .exception ("Error bringing up service" )
226- self .stop ()
227- raise
189+ max_attempts = 3
190+ for attempt in range (max_attempts ):
191+ try :
192+ process , endpoint = self .start_process ()
193+ wait_secs = .1
194+ channel_options = [
195+ ("grpc.max_receive_message_length" , - 1 ),
196+ ("grpc.max_send_message_length" , - 1 ),
197+ # Default: 20000ms (20s), increased to 10 minutes for stability
198+ ("grpc.keepalive_timeout_ms" , 600_000 ),
199+ # Default: 2, set to 0 to allow unlimited pings without data
200+ ("grpc.http2.max_pings_without_data" , 0 ),
201+ # Default: False, set to True to allow keepalive pings when no calls
202+ ("grpc.keepalive_permit_without_calls" , True ),
203+ # Default: 2, set to 0 to allow unlimited ping strikes
204+ ("grpc.http2.max_ping_strikes" , 0 ),
205+ # Default: 0 (disabled), enable socket reuse for better handling
206+ ("grpc.so_reuseport" , 1 ),
207+ ]
208+ self ._grpc_channel = grpc .insecure_channel (
209+ endpoint , options = channel_options )
210+ channel_ready = grpc .channel_ready_future (self ._grpc_channel )
211+ while True :
212+ if process is not None and process .poll () is not None :
213+ _LOGGER .error ("Started job service with %s" , process .args )
214+ raise RuntimeError (
215+ 'Service failed to start up with error %s' % process .poll ())
216+ try :
217+ channel_ready .result (timeout = wait_secs )
218+ break
219+ except (grpc .FutureTimeoutError , grpc .RpcError ):
220+ wait_secs *= 1.2
221+ logging .log (
222+ logging .WARNING if wait_secs > 1 else logging .DEBUG ,
223+ 'Waiting for grpc channel to be ready at %s.' ,
224+ endpoint )
225+ return self ._stub_class (self ._grpc_channel )
226+ except Exception as e :
227+ _LOGGER .warning (
228+ "Error bringing up service on attempt %d: %s" ,
229+ attempt + 1 ,
230+ e ,
231+ exc_info = True )
232+ self .stop ()
233+ if attempt == max_attempts - 1 :
234+ raise
235+ time .sleep (1 )
228236
229237 def start_process (self ):
230238 if self ._owner_id is not None :
0 commit comments