slazarov / python-signalr-client

SignalR client for python based on asyncio.
MIT License
33 stars 22 forks source link

Websocket error handling #11

Open Redferne opened 6 years ago

Redferne commented 6 years ago

My websocket connection towards the signalr endpoint seems to drop every now and then, is there any way to capture this exception and reconnect? My lack of Python-fu is sever.

    message = await ws.recv()
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 350, in recv
    yield from self.ensure_open()
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 501, in ensure_open
    self.close_code, self.close_reason) from self.transfer_data_exc
websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1006 (connection closed abnormally [internal]), no reason

I'm using the following code:

            try:
                connection = Connection(self._stream, session=session)
                hub = connection.register_hub('myHub')
                connection.received += self.on_signalr_debug
                connection.error += self.on_signalr_error
                hub.client.on('NewStuff', self.on_signalr_stuff)
                connection.start()
                hub.server.invoke('authenticate', login, token)
                hub.server.invoke('coolStuff', mystuff)
            except Exception as err:
                _LOGGER.exception("Exception (%s) from SignalR", str(err))

But the Exception is never triggered? Because everything runs in asyncio in eventloop?

slazarov commented 6 years ago

Can you try using the dev branch? It has experimental reconnection mechanism.

Redferne commented 6 years ago

Yes. I tried the dev branch and got this after a few hours:

Traceback (most recent call last):
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 528, in transfer_data
    msg = yield from self.read_message()
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 580, in read_message
    frame = yield from self.read_data_frame(max_size=self.max_size)
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 645, in read_data_frame
    frame = yield from self.read_frame(max_size)
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 710, in read_frame
    extensions=self.extensions,
  File "/srv/code/lib/python3.6/site-packages/websockets/framing.py", line 100, in read
    data = yield from reader(2)
  File "/usr/lib/python3.6/asyncio/streams.py", line 674, in readexactly
    yield from self._wait_for_data('readexactly')
  File "/usr/lib/python3.6/asyncio/streams.py", line 464, in _wait_for_data
    yield from self._waiter
  File "/usr/lib/python3.6/asyncio/selector_events.py", line 727, in _read_ready
    data = self._sock.recv(self.max_size)
ConnectionResetError: [Errno 104] Connection reset by peer

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/srv/code/lib/python3.6/site-packages/signalr_aio/transports/_transport.py", line 105, in _consumer_handler
    message = await asyncio.wait_for(ws.recv(), timeout=self._timeout)
  File "/usr/lib/python3.6/asyncio/tasks.py", line 358, in wait_for
    return fut.result()
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 350, in recv
    yield from self.ensure_open()
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 501, in ensure_open
    self.close_code, self.close_reason) from self.transfer_data_exc
websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1006 (connection closed abnormally [internal]), no reason

Not sure how to capture this exception, I would love to be able to catch any connection errors, I can handle the reconnection myself. Grateful for any pointers. :smile: