"""Kill port 8001 holders, then start ai-service.""" from __future__ import annotations import os import subprocess import sys import time import urllib.request from pathlib import Path ROOT = Path(__file__).resolve().parents[1] LOG = ROOT / ".runtime" / "logs" LOG.mkdir(parents=True, exist_ok=True) def pids_on_port(port: int) -> list[int]: out = subprocess.check_output(["netstat", "-ano"], text=True, errors="replace") pids: set[int] = set() needle = f":{port}" for line in out.splitlines(): if needle not in line: continue if "LISTENING" not in line.upper(): continue parts = line.split() try: pids.add(int(parts[-1])) except ValueError: pass return sorted(pids) def kill_pid(pid: int) -> None: if pid <= 0: return subprocess.run(["taskkill", "/F", "/T", "/PID", str(pid)], check=False, capture_output=True) def main() -> None: print("stopping old ai...") # stop watchdog first if present wd = LOG / "watchdog.pid" if wd.is_file(): try: kill_pid(int(wd.read_text(encoding="ascii").strip())) except ValueError: pass wd.unlink(missing_ok=True) for name in ("ai-service.pid",): pf = LOG / name if pf.is_file(): try: kill_pid(int(pf.read_text(encoding="ascii").strip())) except ValueError: pass for pid in pids_on_port(8001): print(f" free 8001 pid={pid}") kill_pid(pid) time.sleep(2) env = os.environ.copy() env["WEB_BASE"] = "http://127.0.0.1:5173" env["PLATFORM_BASE"] = "http://127.0.0.1:8888" env["GATEWAY_BASE"] = "http://127.0.0.1:8180" env["GENERATE_LOG_DIR"] = str(LOG / "generate") env["FIDELITY_SHOT_DIR"] = str(ROOT / ".runtime" / "fidelity_shots") stamp = time.strftime("%H%M%S") out_path = LOG / f"ai-service.{stamp}.out.log" err_path = LOG / f"ai-service.{stamp}.err.log" out_f = out_path.open("w", encoding="utf-8") err_f = err_path.open("w", encoding="utf-8") # also point stable names via copies later; use unique to avoid locks (LOG / "ai-service.out.log.path").write_text(str(out_path), encoding="utf-8") flags = getattr(subprocess, "CREATE_NO_WINDOW", 0) p = subprocess.Popen( [ sys.executable, "-m", "uvicorn", "app:app", "--host", "127.0.0.1", "--port", "8001", "--reload", ], cwd=str(ROOT / "ai-service"), env=env, stdout=out_f, stderr=err_f, creationflags=flags, ) (LOG / "ai-service.pid").write_text(str(p.pid), encoding="ascii") print(f"started ai-service pid={p.pid}") print(f" logs: {out_path.name} / {err_path.name}") for i in range(45): time.sleep(1) try: with urllib.request.urlopen("http://127.0.0.1:8001/docs", timeout=2) as r: if r.status == 200: print("OK AI http://127.0.0.1:8001") return except Exception as e: if i % 5 == 4: print(f" waiting... ({type(e).__name__})") # show err log snippet try: print(err_path.read_text(encoding="utf-8", errors="replace")[-400:]) except Exception: pass raise SystemExit("AI failed to become ready on :8001") if __name__ == "__main__": main()