| import subprocess |
| import os |
| import sys |
| import time |
| import signal |
|
|
| def main(): |
| print("=== Nexus AI - Hugging Face Spaces Supervisor ===") |
| |
| |
| sys.stdout.reconfigure(line_buffering=True) |
| sys.stderr.reconfigure(line_buffering=True) |
| |
| |
| env = os.environ.copy() |
| env["PYTHONUNBUFFERED"] = "1" |
| |
| |
| env_audio = env.copy() |
| env_audio["WORKER_TYPE"] = "audio" |
| |
| env_ml = env.copy() |
| env_ml["WORKER_TYPE"] = "ml" |
| |
| |
| processes = {} |
| |
| print("Starting Audio Worker process...") |
| processes["audio_worker"] = subprocess.Popen( |
| [sys.executable, "src/workers/run_worker.py"], |
| env=env_audio |
| ) |
| |
| print("Starting ML Worker process...") |
| processes["ml_worker"] = subprocess.Popen( |
| [sys.executable, "src/workers/run_worker.py"], |
| env=env_ml |
| ) |
| |
| |
| port = int(os.getenv("PORT", "7860")) |
| print(f"Starting FastAPI server on port {port}...") |
| processes["api_server"] = subprocess.Popen( |
| [sys.executable, "-m", "uvicorn", "src.api.server:app", "--host", "0.0.0.0", "--port", str(port)], |
| env=env |
| ) |
| |
| def terminate_all(signum, frame): |
| print(f"Received signal {signum}. Terminating all processes...") |
| for name, proc in processes.items(): |
| if proc.poll() is None: |
| print(f"Terminating {name}...") |
| proc.terminate() |
| sys.exit(0) |
| |
| signal.signal(signal.SIGTERM, terminate_all) |
| signal.signal(signal.SIGINT, terminate_all) |
| |
| |
| try: |
| while True: |
| time.sleep(5) |
| |
| |
| if processes["api_server"].poll() is not None: |
| ret = processes["api_server"].returncode |
| print(f"CRITICAL: API server exited with code {ret}. Exiting supervisor.") |
| terminate_all(signal.SIGTERM, None) |
| sys.exit(ret) |
| |
| |
| if processes["audio_worker"].poll() is not None: |
| print("WARNING: Audio worker died. Restarting...") |
| processes["audio_worker"] = subprocess.Popen( |
| [sys.executable, "src/workers/run_worker.py"], |
| env=env_audio |
| ) |
| |
| |
| if processes["ml_worker"].poll() is not None: |
| print("WARNING: ML worker died. Restarting...") |
| processes["ml_worker"] = subprocess.Popen( |
| [sys.executable, "src/workers/run_worker.py"], |
| env=env_ml |
| ) |
| except Exception as e: |
| print(f"Supervisor error: {e}") |
| terminate_all(signal.SIGTERM, None) |
|
|
| if __name__ == "__main__": |
| main() |
|
|