"""Проверка запущенного стенда (make up): api, очередь, воркер с Chrome, удержание окна. make smoke API_KEY=rbx_... # http://localhost:8000 make smoke API_KEY=rbx_... API_URL=https://app.robotex.sokolab.xyz Ключ: make key-create name=smoke. """ import sys import time import httpx URL = "https://example.com" READ_TITLE = [{"type": "inner_html", "selector": "title"}] def check(cond: bool, what: str) -> None: print((" ok " if cond else " FAIL ") + what) if not cond: sys.exit(1) def wait_task(client: httpx.Client, task_id: str, timeout: float = 180) -> dict: deadline = time.monotonic() + timeout while time.monotonic() < deadline: task = client.get(f"/v2/tasks/{task_id}").json() if task["status"] not in ("queued", "running"): return task time.sleep(0.5) raise TimeoutError(f"task {task_id} not finished in {timeout}s") def windows(client: httpx.Client) -> int: return sum(w["windows"] for w in client.get("/health").json()["workers"]) def main(base_url: str, api_key: str) -> None: headers = {"X-API-Key": api_key} client = httpx.Client(base_url=base_url, timeout=300, headers=headers) print("auth") resp = httpx.post(f"{base_url}/v1/solve", json={"url": URL, "actions": []}, timeout=30) check(resp.status_code == 401, f"no key -> {resp.status_code}") print("health") health = client.get("/health").json() check(len(health["workers"]) > 0, f"workers: {[w['worker_id'] for w in health['workers']]}, free slots {health['free_slots']}") print("v1 /v1/solve") started = time.monotonic() data = client.post("/v1/solve", json={"url": URL, "actions": READ_TITLE}).json() check(data["status"] == "ok", f"status {data['status']} {data.get('error', '')} ({time.monotonic() - started:.1f}s)") check(data["actions"][0]["result"] == "Example Domain", "title = Example Domain") print("v2 window held between tasks") v2 = httpx.Client(base_url=base_url, timeout=60, headers=headers) # своя сессия started = time.monotonic() created = v2.post("/v2/tasks", json={"url": URL, "actions": READ_TITLE, "browser_idle_timeout": 2}) check(created.status_code == 202, f"POST /v2/tasks -> {created.status_code}") task = wait_task(v2, created.json()["task_id"]) check(task["status"] == "done" and task["result"]["status"] == "ok", f"first task done ({time.monotonic() - started:.1f}s)") check(windows(client) >= 1, "window stays open") started = time.monotonic() created = v2.post("/v2/tasks", json={"actions": READ_TITLE, "browser_idle_timeout": 2}) task = wait_task(v2, created.json()["task_id"]) check( task["status"] == "done" and task["result"]["actions"][0]["result"] == "Example Domain", f"second task without url ran in the open window ({time.monotonic() - started:.1f}s)", ) check(client.get(f"/v2/tasks/{created.json()['task_id']}").status_code == 404, "task hidden from other sessions") check(v2.delete("/v2/sessions/current").json() == {"closed": True}, "DELETE /v2/sessions/current") deadline = time.monotonic() + 15 while windows(client) and time.monotonic() < deadline: time.sleep(0.5) check(windows(client) == 0, "window closed, slot released") print("all good") if __name__ == "__main__": if len(sys.argv) < 3 or not sys.argv[2]: sys.exit("usage: smoke.py (make smoke API_KEY=...)") main(sys.argv[1], sys.argv[2])