def handle_exception(): """ Context manager translating network related exceptions to custom :mod:`~galaxy.api.errors`. """ try: yield except asyncio.TimeoutError: raise BackendTimeout() except aiohttp.ServerDisconnectedError: raise BackendNotAvailable() except aiohttp.ClientConnectionError: raise NetworkError() except aiohttp.ContentTypeError as error: raise UnknownBackendResponse(error.message) except aiohttp.ClientResponseError as error: if error.status == HTTPStatus.UNAUTHORIZED: raise AuthenticationRequired(error.message) if error.status == HTTPStatus.FORBIDDEN: raise AccessDenied(error.message) if error.status == HTTPStatus.SERVICE_UNAVAILABLE: raise BackendNotAvailable(error.message) if error.status == HTTPStatus.TOO_MANY_REQUESTS: raise TooManyRequests(error.message) if error.status >= 500: raise BackendError(error.message) if error.status >= 400: logger.warning("Got status %d while performing %s request for %s", error.status, error.request_info.method, str(error.request_info.url)) raise UnknownError(error.message) except aiohttp.ClientError as e: logger.exception("Caught exception while performing request") raise UnknownError(repr(e))
async def request(self, method, url, *args, **kwargs): try: response = await self._session.request(method, url, *args, **kwargs) except asyncio.TimeoutError: raise BackendTimeout() except aiohttp.ServerDisconnectedError: raise BackendNotAvailable() except aiohttp.ClientConnectionError: raise NetworkError() except aiohttp.ContentTypeError: raise UnknownBackendResponse() except aiohttp.ClientError: logging.exception( "Caught exception while running {} request for {}".format( method, url)) raise UnknownError() if response.status == HTTPStatus.UNAUTHORIZED: raise AuthenticationRequired() if response.status == HTTPStatus.FORBIDDEN: raise AccessDenied() if response.status == HTTPStatus.SERVICE_UNAVAILABLE: raise BackendNotAvailable() if response.status == HTTPStatus.TOO_MANY_REQUESTS: raise TooManyRequests() if response.status >= 500: raise BackendError() if response.status >= 400: logging.warning( "Got status {} while running {} request for {}".format( response.status, method, url)) raise UnknownError() return response
async def _request(self, method, *args, **kwargs): try: response = await self._session.request(method, *args, **kwargs) except asyncio.TimeoutError: raise BackendTimeout() except aiohttp.ClientConnectionError: raise NetworkError() logging.debug(f"Request response status: {response.status}") if response.status == HTTPStatus.UNAUTHORIZED: raise AuthenticationRequired() if response.status == HTTPStatus.FORBIDDEN: raise AccessDenied() if response.status == HTTPStatus.SERVICE_UNAVAILABLE: raise BackendNotAvailable() if response.status >= 500: raise BackendError() if response.status >= 400: raise UnknownError() return response
protocol_client.wait_closed.return_value = async_return_value(None) websocket.close.return_value = async_return_value(None) websocket.wait_closed.return_value = async_return_value(None) await client.run() assert servers_cache.get.call_count == 2 assert protocol_client.authenticate.call_count == 2 assert protocol_client.run.call_count == 2 @pytest.mark.asyncio @pytest.mark.parametrize( "exception", [BackendNotAvailable(), BackendTimeout(), BackendError(), NetworkError()]) async def test_servers_cache_retry(client, protocol_client, backend_client, servers_cache, websocket, mocker, exception): servers_cache.get.side_effect = [ async_raise(exception), async_return_value(["wss://abc.com/websocket"]) ] sleep = mocker.patch("protocol.websocket_client.asyncio.sleep", side_effect=lambda x: async_return_value(None)) backend_client.get_authentication_data.return_value = STEAM_ID, ACCOUNT_NAME, TOKEN protocol_client.authenticate.return_value = async_return_value(None) protocol_client.run.return_value = async_raise( websockets.ConnectionClosedOK(1000, ""), 10) await client.run() sleep.assert_any_call(RECONNECT_INTERVAL_SECONDS)
async_raise(websockets.ConnectionClosedError(1002, ""), 10), async_raise(websockets.ConnectionClosedOK(1000, ""), 10) ] protocol_client.close.return_value = async_return_value(None) protocol_client.wait_closed.return_value = async_return_value(None) websocket.close.return_value = async_return_value(None) websocket.wait_closed.return_value = async_return_value(None) await client.run() assert servers_cache.get.call_count == 2 assert protocol_client.authenticate.call_count == 2 assert protocol_client.run.call_count == 2 @pytest.mark.asyncio @pytest.mark.parametrize("exception", [ BackendNotAvailable(), BackendTimeout(), BackendError(), NetworkError() ]) async def test_servers_cache_retry( client, protocol_client, backend_client, servers_cache, websocket, mocker, exception ): servers_cache.get.side_effect = [ async_raise(exception), async_return_value(["wss://abc.com/websocket"]) ] sleep = mocker.patch("protocol.websocket_client.asyncio.sleep", side_effect=lambda x: async_return_value(None)) backend_client.get_authentication_data.return_value = STEAM_ID, ACCOUNT_NAME, TOKEN protocol_client.authenticate.return_value = async_return_value(None) protocol_client.run.return_value = async_raise(websockets.ConnectionClosedOK(1000, ""), 10) await client.run() sleep.assert_any_call(RECONNECT_INTERVAL_SECONDS)