sivulich / mqttasgi

MQTT ASGI Protocol Server
MIT License
34 stars 15 forks source link

MQTT lost subscription when connect_max_retries is set to 0 #18

Closed andreatoppan closed 1 year ago

andreatoppan commented 1 year ago

Hello! thanks for the project, I find it very useful. I realized a consumer that will listen to some mqtt topics. I noticed that if I unplug the network cable, wait more than 60 seconds and replug it the client will reconnect, however no more messages will be received on the subscribed topics. I placed the topic subscription on the connect event handler and the topic unsubscription on the disconnect event handler. What is happening is that once the client detects the disconnection it won't trigger the disconnect event handler, and when it is connecting again it will not subscribe the topics as they are already present in the topic list. For this reason no more messages are received after the disconnection. A workaround for this is to add some additional logic on the connect handler, that will check if the topics were previously subscribed, and, if so, it will unsubscribe before subscribing it again. I don't know if this is an issue or it is simply wrong the way I am using this software.

I also think that adding the keepalive option to the client options would be useful, what do you think?

Attached the code of the consumer

class MQTTChannelsConsumer(MqttConsumer):
    groupName = 'frontend'
    topics = [
        { "topic": "topic1", "qos": 2},
        { "topic": "topic2", "qos": 2},
    ]
    already_subscribed_topics = []

    async def connect(self):
        logger.debug('[mqttasgi][consumer][connect] - Connected!')
        for topic in self.topics:
            if topic["topic"] in self.already_subscribed_topics:
                #unsubscribing topic before resubscribing
                await self.unsubscribe(topic["topic"])

            await self.subscribe(topic["topic"], topic["qos"])
            self.already_subscribed_topics.append(topic["topic"])

    async def receive(self, mqtt_message):
        logger.debug('Received a message at topic:', mqtt_message["topic"])
        logger.debug('With payload', mqtt_message["payload"])
        logger.debug('And QOS:', mqtt_message["qos"])

    async def disconnect(self):
        logger.debug('[mqttasgi][consumer][disconnect] - Disconnected!')
        for topic in self.topics:
            await self.unsubscribe(topic["topic"])

Thank you and have a good day. A.

sivulich commented 1 year ago

Hello Andrea!

Thanks for flagging this, I will look into it and get back to you. I’m currently away until next week, but will work on it once I’m back.

If the max retries fail it should kill the processes and your process manager should handle the restart. But you should get the disconnect event.

Kind regards, S

On Tue, 31 Jan 2023 at 19:07 andreatoppan @.***> wrote:

Hello! thanks for the project, I find it very useful. I realized a consumer that will listen to some mqtt topics. I noticed that if I unplug the network cable, wait more than 60 seconds and replug it the client will reconnect, however no more messages will be received on the subscribed topics. I placed the topic subscription on the connect event handler and the topic unsubscription on the disconnect event handler. What is happening is that once the client detects the disconnection it won't trigger the disconnect event handler, and when it is connecting again it will not subscribe the topics as they are already present in the topic list. For this reason no more messages are received after the disconnection. A workaround for this is to add some additional logic on the connect handler, that will check if the topics were previously subscribed, and, if so, it will unsubscribe before subscribing it again. I don't know if this is an issue or it is simply wrong the way I am using this software.

I also think that adding the keepalive option to the client options would be useful, what do you think?

Attached the code of the consumer ` class MQTTChannelsConsumer(MqttConsumer): groupName = 'frontend' topics = [ { "topic": "topic1", "qos": 2}, { "topic": "topic2", "qos": 2}, ] already_subscribed_topics = []

async def connect(self): logger.debug('[mqttasgi][consumer][connect] - Connected!') for topic in self.topics: if topic["topic"] in self.already_subscribed_topics:

unsubscribing topic before resubscribing

        await self.unsubscribe(topic["topic"])

    await self.subscribe(topic["topic"], topic["qos"])
    self.already_subscribed_topics.append(topic["topic"])

async def receive(self, mqtt_message): logger.debug('Received a message at topic:', mqtt_message["topic"]) logger.debug('With payload', mqtt_message["payload"]) logger.debug('And QOS:', mqtt_message["qos"])

async def disconnect(self): logger.debug('[mqttasgi][consumer][disconnect] - Disconnected!') for topic in self.topics: await self.unsubscribe(topic["topic"])

`

Thank you and have a good day. A.

— Reply to this email directly, view it on GitHub https://github.com/sivulich/mqttasgi/issues/18, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEMYVUDCZQULDJQEKJ5RU43WVFIENANCNFSM6AAAAAAUMYAOMI . You are receiving this because you are subscribed to this thread.Message ID: @.***>

andreatoppan commented 1 year ago

Oh ok, that's most probably why then, I am using connect_max_retries set to 0 in order to retry indefinitely on the mqtt broker. Anyhow In think that the problem arise even with connect_max_retries set with a value different from 0, if the client reconnect successfully the topic are not resubscribed and therefore no message will be received. Thank you and best regards! Andrea

sivulich commented 1 year ago

We need to verify that because it’s intended behavior, when reconnecting brokers should keep the subscriptions of the client and queues of messages. Are you using the client id and clean session false?

On Tue, 31 Jan 2023 at 20:28 andreatoppan @.***> wrote:

Oh ok, that's most probably why then, I am using connect_max_retries set to 0 in order to retry indefinitely on the mqtt broker. Anyhow In think that the problem arise even with connect_max_retries set with a value different from 0, if the client reconnect successfully the topic are not resubscribed and therefore no message will be received. Thank you and best regards! Andrea

— Reply to this email directly, view it on GitHub https://github.com/sivulich/mqttasgi/issues/18#issuecomment-1410946957, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEMYVUARZLI7BL6272TUT73WVFRUFANCNFSM6AAAAAAUMYAOMI . You are receiving this because you commented.Message ID: @.***>

andreatoppan commented 1 year ago

Hello! You are right, sorry for opening this issue, I will close it now. I didn't specified a clean_session and therefore it was set to true. This explain why I was not receiving the messages after it. Thank you!