wialon/gmqtt

Reconnect Fail

Opened this issue · 2 comments

My client disconnected from broker, but an error occurred while it try to reconnect . The client can't reconnect again but the event_loop still run. Maybe there should be an on_error() callback function set on the client.

I check the source code in `gmqtt.mqtt.handler'

    def _handle_disconnect_packet(self, cmd, packet):
        # reset server topics on disconnect
        self._clear_topics_aliases()

        future = asyncio.ensure_future(self.reconnect(delay=True))
        future.add_done_callback(self._handle_exception_in_future)
        self.on_disconnect(self, packet)

    def _handle_exception_in_future(self, future):
        if future.exception():
            logger.warning('[EXC OCCURED] in reconnect future %s', future.exception())
            return

If the reconnect future run fail, and the callback _handle_exception_in_future Just print a log info ......, Why not do a reconnection after some seconds?

About the on_disconnect() callback (In ‘README.md’)

def on_disconnect(client, packet, exc=None):
    print('Disconnected') 

I define the exe param, but the source code in gmqtt.mqtt.handler

    def _handle_disconnect_packet(self, cmd, packet):
        # reset server topics on disconnect
        self._clear_topics_aliases()

        future = asyncio.ensure_future(self.reconnect(delay=True))
        future.add_done_callback(self._handle_exception_in_future)
        self.on_disconnect(self, packet)

In Fact , self.on_disconnect(self, packet) did not pass an exe param, I want get more exception infomation in the callback() , andI really need it !!!

My solution:

class MyClient(MQTTClient):
    async def reconnect(self, delay=False):
        if not self._allow_reconnect():
            return
        # stopping auto-reconnects during reconnect procedure is important, better do not touch :(
        self._temporatily_stop_reconnect()

    ############# My Solution #################
        try:
            await self._disconnect()
        except Exception as e:
            logger.error('Disconnected Error!')
    ##########################################

        if delay:
            await asyncio.sleep(self._config['reconnect_delay'])
        try:
            self._connection = await self._create_connection(self._host, self._port, ssl=self._ssl,
                                                             clean_session=False, keepalive=self._keepalive)
        except OSError as exc:
            self.failed_connections += 1
            logger.warning("[CAN'T RECONNECT] %s", self.failed_connections)
            asyncio.ensure_future(self.reconnect(delay=True))
            return
        await self._connection.auth(self._client_id, self._username, self._password,
                                    will_message=self._will_message, **self._connect_properties)

I've created a PR (#119) with some instructions on how to reproduce it and a test