"""Launch a vLLM OpenAI server for one quant variant, health-check it, and tear it down by port (never by command-line match — that bit us in Approach A).""" from __future__ import annotations import os import re import subprocess import time import urllib.request from typing import List, Optional # Default seconds to wait for a server to become healthy. Overridable via env so a # method that fails to boot is recorded quickly instead of blocking the sweep. DEFAULT_HEALTH_TIMEOUT = float(os.environ.get("SURYA_QUANT_HEALTH_TIMEOUT", "900")) def health_url(port: int) -> str: return f"http://127.0.0.1:{port}/health" def parse_listening_pid(ss_output: str, port: int) -> Optional[int]: for line in ss_output.splitlines(): if f":{port} " in line or line.rstrip().endswith(f":{port}"): m = re.search(r"pid=(\d+)", line) if m: return int(m.group(1)) return None def wait_healthy(port: int, timeout: float = DEFAULT_HEALTH_TIMEOUT) -> bool: deadline = time.time() + timeout url = health_url(port) while time.time() < deadline: try: with urllib.request.urlopen(url, timeout=2) as resp: if resp.status == 200: return True except Exception: time.sleep(3) return False def start_server(serve_args: List[str], log_path: str) -> subprocess.Popen: cmd = ["python", "-m", "vllm.entrypoints.openai.api_server", *serve_args] log = open(log_path, "w") return subprocess.Popen(cmd, stdout=log, stderr=subprocess.STDOUT) def stop_server(port: int, proc: Optional[subprocess.Popen] = None) -> None: if proc is not None: proc.terminate() try: proc.wait(timeout=30) except Exception: proc.kill() out = subprocess.run(["ss", "-ltnp"], capture_output=True, text=True).stdout pid = parse_listening_pid(out, port) if pid: subprocess.run(["kill", str(pid)])