@@ -284,20 +284,60 @@ def prepare_and_start_backend(
284
284
285
285
instance = ProductInstance (_start_program (args , env_copy ).pid )
286
286
287
+ # Verify that the backend is ready to accept connections
288
+ # before returning the Modeler instance.
289
+ LOG .info ("Waiting for backend to be ready..." )
290
+ _wait_for_backend (host , port , timeout )
291
+
287
292
return Modeler (
288
293
host = host , port = port , timeout = timeout , product_instance = instance , backend_type = backend_type
289
294
)
290
295
291
296
292
- def get_available_port ():
293
- """Return an available port to be used."""
297
+ def get_available_port () -> int :
298
+ """
299
+ Return an available port to be used.
300
+
301
+ Returns
302
+ -------
303
+ int
304
+ The available port.
305
+ """
294
306
sock = socket .socket ()
295
307
sock .bind ((socket .gethostname (), 0 ))
296
308
port = sock .getsockname ()[1 ]
297
309
sock .close ()
298
310
return port
299
311
300
312
313
+ def _wait_for_backend (host : str , port : int , timeout : int ):
314
+ """
315
+ Check if the backend is ready to accept connections.
316
+
317
+ Parameters
318
+ ----------
319
+ host : str
320
+ The backend's ip address.
321
+ port : int
322
+ The backend's port number.
323
+ timeout : int
324
+ The timeout in seconds.
325
+ """
326
+ import time
327
+
328
+ start_time = time .time ()
329
+ while time .time () - start_time < timeout :
330
+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
331
+ if s .connect_ex ((host , port )) == 0 :
332
+ LOG .debug ("Backend is ready to accept connections." )
333
+ return
334
+ else :
335
+ LOG .debug ("Still waiting for backend to be ready... Retrying in 5 seconds." )
336
+ time .sleep (5 )
337
+
338
+ raise ConnectionError ("Timeout while waiting for backend to be ready." )
339
+
340
+
301
341
def _is_port_available (port : int , host : str = "localhost" ) -> bool :
302
342
"""
303
343
Check whether the argument port is available or not.
0 commit comments