Some adjustments with compute WebSocket handling. Ref https://github.com/GNS3/gns3-server/issues/1564

This commit is contained in:
grossmj
2019-04-14 16:48:12 +07:00
parent 6db8cecda5
commit 6dc58b28fd
3 changed files with 43 additions and 18 deletions

View File

@ -150,9 +150,14 @@ class Compute:
self._controller.save()
async def close(self):
self._connected = False
if self._http_session and not self._http_session.closed:
await self._http_session.close()
try:
await self._notifications
except asyncio.CancelledError:
pass
self._closed = True
@property
@ -417,25 +422,36 @@ class Compute:
Connect to the notification stream
"""
async with self._session().ws_connect(self._getUrl("/notifications/ws"), auth=self._auth) as ws:
async for response in ws:
if response.type == aiohttp.WSMsgType.TEXT and response.data:
msg = json.loads(response.data)
action = msg.pop("action")
event = msg.pop("event")
project_id = msg.pop("project_id", None)
if action == "ping":
self._cpu_usage_percent = event["cpu_usage_percent"]
self._memory_usage_percent = event["memory_usage_percent"]
#FIXME: slow down number of compute events
self._controller.notification.controller_emit("compute.updated", self.__json__())
ws_url = self._getUrl("/notifications/ws")
try:
async with self._session().ws_connect(ws_url, auth=self._auth, heartbeat=10) as ws:
log.info("Connected to compute WebSocket '{}'".format(ws_url))
async for response in ws:
if response.type == aiohttp.WSMsgType.TEXT:
msg = json.loads(response.data)
action = msg.pop("action")
event = msg.pop("event")
project_id = msg.pop("project_id", None)
if action == "ping":
self._cpu_usage_percent = event["cpu_usage_percent"]
self._memory_usage_percent = event["memory_usage_percent"]
#FIXME: slow down number of compute events
self._controller.notification.controller_emit("compute.updated", self.__json__())
else:
await self._controller.notification.dispatch(action, event, project_id=project_id, compute_id=self.id)
else:
await self._controller.notification.dispatch(action, event, project_id=project_id, compute_id=self.id)
elif response.type == aiohttp.WSMsgType.CLOSED or response.type == aiohttp.WSMsgType.ERROR or response.data is None:
self._connected = False
break
if response.type == aiohttp.WSMsgType.CLOSE:
await ws.close()
elif response.type == aiohttp.WSMsgType.ERROR:
log.error("Error received on compute WebSocket '{}': {}".format(ws_url, ws.exception()))
elif response.type == aiohttp.WSMsgType.CLOSED:
pass
self._connected = False
break
finally:
log.info("Connection closed to compute WebSocket '{}'".format(ws_url))
# Try to reconnect after 1 seconds if server unavailable only if not during tests (otherwise we create a ressources usage bomb)
# Try to reconnect after 1 second if server unavailable only if not during tests (otherwise we create a ressources usage bomb)
if not hasattr(sys, "_called_from_test") or not sys._called_from_test:
asyncio.get_event_loop().call_later(1, lambda: asyncio.ensure_future(self.connect()))