@@ -221,8 +221,6 @@ async def list_available_models() -> Dict[str, Any]:
221221@app .get ("/health" )
222222async def health_check () -> Dict [str , str ]:
223223 """Check the health status of the server"""
224- # Always return healthy to ensure the server can respond during startup
225- # Even if model is still loading
226224 global model_loading
227225 status = "initializing" if model_loading else "healthy"
228226 return {"status" : status }
@@ -649,52 +647,24 @@ def delayed_exit():
649647
650648 threading .Thread (target = delayed_exit , daemon = True ).start ()
651649
652- def setup_ngrok (port : int = 8000 , max_retries : int = 3 ) -> Optional [str ]:
653- """Setup ngrok tunnel with retry logic and validation"""
650+ def setup_ngrok (port : int = 8000 ) -> Optional [str ]:
651+ """Simple ngrok tunnel setup without any validation or health checks """
654652 ngrok_token = os .getenv ("NGROK_AUTH_TOKEN" )
655653
656654 if not ngrok_token :
657655 logger .error ("NGROK_AUTH_TOKEN environment variable not set" )
658656 return None
659657
660- # Validate token format
661- if not isinstance (ngrok_token , str ) or len (ngrok_token ) < 30 :
662- logger .error ("Invalid NGROK_AUTH_TOKEN format" )
658+ try :
659+ # Configure and start tunnel
660+ conf .get_default ().auth_token = ngrok_token
661+ tunnel = ngrok .connect (port , "http" )
662+ public_url = tunnel .public_url
663+ logger .info (f"Ngrok tunnel established: { public_url } " )
664+ return public_url
665+ except Exception as e :
666+ logger .error (f"Failed to establish ngrok tunnel: { str (e )} " )
663667 return None
664-
665- for attempt in range (max_retries ):
666- try :
667- # Configure ngrok
668- conf .get_default ().auth_token = ngrok_token
669- conf .get_default ().region = "us" # or other region as needed
670-
671- # Kill any existing ngrok processes
672- ngrok .kill ()
673- time .sleep (2 ) # Added delay to allow previous tunnels to close
674-
675- # Start new tunnel
676- tunnel = ngrok .connect (port , "http" )
677-
678- # Verify tunnel
679- public_url = tunnel .public_url
680- if not public_url .startswith ("http" ):
681- raise ValueError ("Invalid tunnel URL" )
682-
683- # Test connection
684- response = requests .get (f"{ public_url } /health" , timeout = 5 )
685- if response .status_code != 200 :
686- raise ConnectionError ("Tunnel health check failed" )
687-
688- logger .info (f"Ngrok tunnel established: { public_url } " )
689- return public_url
690-
691- except Exception as e :
692- logger .warning (f"Ngrok connection attempt { attempt + 1 } failed: { str (e )} " )
693- if attempt < max_retries - 1 :
694- time .sleep (2 ** attempt ) # Exponential backoff
695- continue
696- logger .error ("Failed to establish ngrok tunnel after all retries" )
697- raise
698668
699669# New utility functions added to fix undefined errors
700670
@@ -716,9 +686,8 @@ async def load_model_in_background(model_id: str):
716686# Simplified start_server function that runs directly in the main process
717687def start_server (use_ngrok : bool = False , port = 8000 ):
718688 """Start the LocalLab server directly in the main process"""
719- try :
720- # Display startup banner
721- startup_banner = f"""
689+ # Display startup banner
690+ startup_banner = f"""
722691{ Fore .CYAN }
723692╔══════════════════════════════════════════════════════════════════════╗
724693║ ║
@@ -728,40 +697,41 @@ def start_server(use_ngrok: bool = False, port=8000):
728697
729698{ Fore .YELLOW } ⏳ Initializing server...{ Style .RESET_ALL }
730699"""
731- print (startup_banner , flush = True )
732-
733- # Check if port is already in use
734- if is_port_in_use (port ):
735- logger .warning (f"Port { port } is already in use. Trying to find another port..." )
736- for p in range (port + 1 , port + 100 ):
737- if not is_port_in_use (p ):
738- port = p
739- logger .info (f"Using alternative port: { port } " )
740- break
741- else :
742- raise RuntimeError (f"Could not find an available port in range { port } -{ port + 100 } " )
743-
744- # If using ngrok, set up the tunnel before starting the server
745- if use_ngrok :
746- logger .info (f"{ Fore .CYAN } Setting up ngrok tunnel to port { port } ...{ Style .RESET_ALL } " )
747- public_url = setup_ngrok (port = port )
748- if public_url :
749- ngrok_section = f"\n { Fore .CYAN } ┌────────────────────────── Ngrok Tunnel Details ─────────────────────────────┐{ Style .RESET_ALL } \n │\n │ 🚀 Ngrok Public URL: { Fore .GREEN } { public_url } { Style .RESET_ALL } \n │\n { Fore .CYAN } └──────────────────────────────────────────────────────────────────────────────┘{ Style .RESET_ALL } \n "
750- logger .info (ngrok_section )
751- print (ngrok_section )
752- else :
753- logger .error (f"{ Fore .RED } Failed to create ngrok tunnel. Check your ngrok token.{ Style .RESET_ALL } " )
754- logger .info (f"{ Fore .YELLOW } Server will run locally on port { port } .{ Style .RESET_ALL } " )
755-
756- # Server info section
757- server_section = f"\n { Fore .CYAN } ┌────────────────────────── Server Details ─────────────────────────────┐{ Style .RESET_ALL } \n │\n │ 🖥️ Local URL: { Fore .GREEN } http://localhost:{ port } { Style .RESET_ALL } \n │ ⚙️ Status: { Fore .GREEN } Running{ Style .RESET_ALL } \n │ 🔄 Model Loading: { Fore .YELLOW } In Progress{ Style .RESET_ALL } \n │\n { Fore .CYAN } └──────────────────────────────────────────────────────────────────────────────┘{ Style .RESET_ALL } \n "
758- print (server_section , flush = True )
759-
760- # Set up signal handlers for graceful shutdown
761- signal .signal (signal .SIGINT , signal_handler )
762- signal .signal (signal .SIGTERM , signal_handler )
763-
764- # Start uvicorn server directly in the main process
700+ print (startup_banner , flush = True )
701+
702+ # Check if port is already in use
703+ if is_port_in_use (port ):
704+ logger .warning (f"Port { port } is already in use. Trying to find another port..." )
705+ for p in range (port + 1 , port + 100 ):
706+ if not is_port_in_use (p ):
707+ port = p
708+ logger .info (f"Using alternative port: { port } " )
709+ break
710+ else :
711+ raise RuntimeError (f"Could not find an available port in range { port } -{ port + 100 } " )
712+
713+ # Server info section
714+ server_section = f"\n { Fore .CYAN } ┌────────────────────────── Server Details ─────────────────────────────┐{ Style .RESET_ALL } \n │\n │ 🖥️ Local URL: { Fore .GREEN } http://localhost:{ port } { Style .RESET_ALL } \n │ ⚙️ Status: { Fore .GREEN } Running{ Style .RESET_ALL } \n │ 🔄 Model Loading: { Fore .YELLOW } In Progress{ Style .RESET_ALL } \n │\n { Fore .CYAN } └──────────────────────────────────────────────────────────────────────────────┘{ Style .RESET_ALL } \n "
715+ print (server_section , flush = True )
716+
717+ # Set up ngrok before starting server if requested
718+ public_url = None
719+ if use_ngrok :
720+ logger .info (f"{ Fore .CYAN } Setting up ngrok tunnel to port { port } ...{ Style .RESET_ALL } " )
721+ public_url = setup_ngrok (port = port )
722+ if public_url :
723+ ngrok_section = f"\n { Fore .CYAN } ┌────────────────────────── Ngrok Tunnel Details ─────────────────────────────┐{ Style .RESET_ALL } \n │\n │ 🚀 Ngrok Public URL: { Fore .GREEN } { public_url } { Style .RESET_ALL } \n │\n { Fore .CYAN } └──────────────────────────────────────────────────────────────────────────────┘{ Style .RESET_ALL } \n "
724+ logger .info (ngrok_section )
725+ print (ngrok_section )
726+ else :
727+ logger .warning (f"{ Fore .YELLOW } Failed to set up ngrok tunnel. Server will run locally on port { port } .{ Style .RESET_ALL } " )
728+
729+ # Set up signal handlers for graceful shutdown
730+ signal .signal (signal .SIGINT , signal_handler )
731+ signal .signal (signal .SIGTERM , signal_handler )
732+
733+ # Start uvicorn server directly in the main process
734+ try :
765735 if use_ngrok :
766736 # Colab environment setup
767737 import nest_asyncio
@@ -774,17 +744,19 @@ def start_server(use_ngrok: bool = False, port=8000):
774744 # Local environment
775745 logger .info (f"Starting server on port { port } (local mode)" )
776746 uvicorn .run (app , host = "127.0.0.1" , port = port , reload = False , workers = 1 , log_level = "info" )
777-
778747 except Exception as e :
748+ # Clean up ngrok if server fails to start
749+ if use_ngrok and public_url :
750+ try :
751+ ngrok .disconnect (public_url )
752+ except :
753+ pass
779754 logger .error (f"Server startup failed: { str (e )} " )
780755 logger .error (traceback .format_exc ())
781756 raise
782757
783758if __name__ == "__main__" :
784- # Setup signal handlers
785- signal .signal (signal .SIGINT , signal_handler )
786- signal .signal (signal .SIGTERM , signal_handler )
787-
788- # Start the server with ngrok if in Colab
759+ # Start the server with ngrok if requested via environment variable
789760 use_ngrok = os .getenv ("ENABLE_NGROK" , "false" ).lower () == "true"
790- start_server (use_ngrok = use_ngrok )
761+ port = int (os .getenv ("SERVER_PORT" , "8000" ))
762+ start_server (use_ngrok = use_ngrok , port = port )
0 commit comments