async def _send_final_payload(self, payload: Payload, *,
                                  headers: Headers) -> JsonObject:
        try:
            session = await self._get_http_session()
            async with self._http_semaphore:
                response = await session.post(self._url, json=payload,
                                              ssl=self.ssl, headers=headers,
                                              timeout=self.request_timeout)
            response_payload = await response.json(loads=self._json_loads)
            headers = response.headers
        except aiohttp.client_exceptions.ClientError as error:
            LOGGER.warning("Failed to send payload, %s", error)
            raise TransportError(str(error)) from error
        response_message = await self._consume_payload(
            response_payload,
            headers=headers,
            find_response_for=payload[0]
        )

        if response_message is None:
            error_message = "No response message received for the " \
                            "first message in the payload"
            LOGGER.warning(error_message)
            raise TransportError(error_message)
        return response_message
Beispiel #2
0
    async def _receive(self, socket: WebSocket) -> None:
        """Consume the incomming messages on the given *socket*

        :param socket: A Websocket object
        """
        # receive responses from the server and consume them
        try:
            while True:
                response = await socket.receive()
                if response.type == aiohttp.WSMsgType.CLOSE:
                    raise TransportConnectionClosed("Received CLOSE message "
                                                    "on the factory.")
                # parse the response payload
                try:
                    response_payload \
                        = cast(Payload, response.json(loads=self._json_loads))
                except TypeError:
                    raise TransportError("Received invalid response from the "
                                         "server.")

                # consume all event messages in the payload
                await self._consume_payload(response_payload)

                # set results of matching exchanges
                self._set_exchange_results(response_payload)
        except Exception as error:
            # set the error as the result for all pending exchanges
            self._set_exchange_errors(error)
            raise
Beispiel #3
0
    async def test_context_manager_on_enter_error(self):
        self.client.open = mock.CoroutineMock(side_effect=TransportError())
        self.client.close = mock.CoroutineMock()

        with self.assertRaises(TransportError):
            async with self.client:
                pass

        self.client.open.assert_called()
        self.client.close.assert_called()
Beispiel #4
0
    async def test_disconnect_transport_error(self):
        self.transport._state = TransportState.CONNECTED
        self.transport._stop_connect_task = mock.CoroutineMock()
        self.transport._send_message = mock.CoroutineMock(
            side_effect=TransportError())

        await self.transport.disconnect()

        self.assertEqual(self.transport.state, TransportState.DISCONNECTED)
        self.transport._stop_connect_task.assert_called()
        self.transport._send_message.assert_called_with(DISCONNECT_MESSAGE)
Beispiel #5
0
    async def test_close_on_transport_error(self):
        self.client._closed = False
        self.client._transport = mock.MagicMock()
        self.client._transport.client_id = "client_id"
        error = TransportError("description")
        self.client._transport.disconnect = mock.CoroutineMock(
            side_effect=error)
        self.client._transport.close = mock.CoroutineMock()
        expected_log = [
            "INFO:aiocometd.client:Closing client...",
            "INFO:aiocometd.client:Client closed."
        ]

        with self.assertLogs("aiocometd.client", "DEBUG") as log:
            with self.assertRaisesRegex(TransportError, str(error)):
                await self.client.close()

        self.assertEqual(log.output, expected_log)
        self.client._transport.disconnect.assert_called()
        self.client._transport.close.assert_not_called()
        self.assertTrue(self.client.closed)
Beispiel #6
0
 async def _send_final_payload(self, payload: Payload, *,
                               headers: Headers) -> JsonObject:
     try:
         try:
             # try to send the payload on the socket which might have
             # been closed since the last time it was used
             socket = await self._get_socket(headers)
             return await self._send_socket_payload(socket, payload)
         except asyncio.TimeoutError:
             # reset the socket factory since after a timeout error
             # it becomes invalid
             await self._reset_socket()
             raise
         except TransportConnectionClosed:
             # if the socket was indeed closed, try to reopen the socket
             # and send the payload, since the connection could've
             # normalised since the last network problem
             socket = await self._get_socket(headers)
             return await self._send_socket_payload(socket, payload)
     except aiohttp.client_exceptions.ClientError as error:
         LOGGER.warning("Failed to send payload, %s", error)
         raise TransportError(str(error)) from error