chore: initial commit of ai site platform
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
120
scripts/restart_ai_only.py
Normal file
120
scripts/restart_ai_only.py
Normal file
@@ -0,0 +1,120 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user