fix(desktop): keep cold gateway config off event loop
This commit is contained in:
parent
fe9bdd17e3
commit
579672d87d
|
|
@ -2953,6 +2953,20 @@ def _collect_profile_gateway_topology_cached() -> Dict[str, Any]:
|
|||
return data
|
||||
|
||||
|
||||
def _load_configured_gateway_platforms() -> set[str]:
|
||||
"""Load connected platform names away from the asyncio event loop.
|
||||
|
||||
The first ``load_gateway_config()`` call performs platform discovery and
|
||||
can take longer than Desktop's WebSocket connect timeout on Windows. This
|
||||
helper is synchronous by design; ``get_status`` runs it in Starlette's
|
||||
worker pool so a concurrent ``/api/ws`` handshake can still complete.
|
||||
"""
|
||||
from gateway.config import load_gateway_config
|
||||
|
||||
gateway_config = load_gateway_config()
|
||||
return {platform.value for platform in gateway_config.get_connected_platforms()}
|
||||
|
||||
|
||||
@app.get("/api/ssh/ownership")
|
||||
async def get_ssh_ownership(request: Request):
|
||||
_require_token(request)
|
||||
|
|
@ -3054,12 +3068,9 @@ async def get_status(profile: Optional[str] = None):
|
|||
gateway_updated_at = None
|
||||
configured_gateway_platforms: set[str] | None = None
|
||||
try:
|
||||
from gateway.config import load_gateway_config
|
||||
|
||||
gateway_config = load_gateway_config()
|
||||
configured_gateway_platforms = {
|
||||
platform.value for platform in gateway_config.get_connected_platforms()
|
||||
}
|
||||
configured_gateway_platforms = await run_in_threadpool(
|
||||
_load_configured_gateway_platforms
|
||||
)
|
||||
except Exception:
|
||||
configured_gateway_platforms = None
|
||||
|
||||
|
|
|
|||
|
|
@ -318,6 +318,39 @@ class TestWebServerEndpoints:
|
|||
monitor.close()
|
||||
writer.close()
|
||||
|
||||
def test_get_status_loads_gateway_config_off_event_loop(self, monkeypatch):
|
||||
"""Cold gateway config loading must not block the WebSocket loop.
|
||||
|
||||
On Windows the first ``load_gateway_config()`` call imports and
|
||||
discovers platform adapters and can take longer than Desktop's 15s
|
||||
WebSocket timeout. Running it inline makes a concurrent /api/ws
|
||||
handshake time out before ``gateway.ready`` can be sent.
|
||||
"""
|
||||
import gateway.config as gateway_config
|
||||
import hermes_cli.web_server as web_server
|
||||
|
||||
seen = {}
|
||||
|
||||
class _Config:
|
||||
@staticmethod
|
||||
def get_connected_platforms():
|
||||
return []
|
||||
|
||||
def _load():
|
||||
seen["thread"] = threading.get_ident()
|
||||
return _Config()
|
||||
|
||||
monkeypatch.setattr(gateway_config, "load_gateway_config", _load)
|
||||
|
||||
async def _run():
|
||||
event_loop_thread = threading.get_ident()
|
||||
await web_server.get_status()
|
||||
return event_loop_thread
|
||||
|
||||
event_loop_thread = asyncio.run(_run())
|
||||
|
||||
assert seen["thread"] != event_loop_thread
|
||||
|
||||
def test_get_sessions_auto_archive_uses_maintenance_writer(self):
|
||||
from hermes_cli import web_server
|
||||
from hermes_cli.config import load_config, save_config
|
||||
|
|
|
|||
Loading…
Reference in New Issue