diff --git a/bin/nexus_window.py b/bin/nexus_window.py index aab5396..9769549 100644 --- a/bin/nexus_window.py +++ b/bin/nexus_window.py @@ -60,7 +60,11 @@ def _wait_for_backend(timeout: float = 40.0) -> bool: deadline = time.time() + timeout while time.time() < deadline: try: - with urllib.request.urlopen(status_url, timeout=2) as r: + # 5s, not 2: /status probes Ollama, and a wedged Ollama made it + # slower than a 2s ceiling - the backend was up and answering 200 + # while this loop timed out on every attempt and declared it dead. + # The server side is fixed too; this is the margin. + with urllib.request.urlopen(status_url, timeout=5) as r: if r.status == 200: return True except Exception: diff --git a/synapse/main.py b/synapse/main.py index 2209e62..7e714ce 100644 --- a/synapse/main.py +++ b/synapse/main.py @@ -211,7 +211,12 @@ async def startup_event(): @app.get("/status") async def root(): try: - status = ollama.get_status() if (ollama is not None and hasattr(ollama, "get_status")) else None + # to_thread, not a direct call: get_status() does blocking IO (an httpx + # request and, once, a subprocess). Awaiting it inline stalled the whole + # event loop on every poll - and the UI polls /status continuously, so + # the server froze in lockstep with its own health check. + status = (await _asyncio.to_thread(ollama.get_status) + if (ollama is not None and hasattr(ollama, "get_status")) else None) except Exception: status = None return {"status": "online", "version": VERSION, "ollama": status}