hivemq / hivemq-mqtt-client

HiveMQ MQTT Client is an MQTT 5.0 and MQTT 3.1.1 compatible and feature-rich high-performance Java client library with different API flavours and backpressure support
https://hivemq.github.io/hivemq-mqtt-client/
Apache License 2.0
860 stars 159 forks source link

[Persistent Sessions] Broker sends message before re-subscribing #521

Closed sirtoobii closed 2 years ago

sirtoobii commented 2 years ago

Expected behavior

A client starts a session and subscribes to various topics. After some time, the client disconnects (not unexpectedly) and then reconnects again with cleanSession=false, subscribes to the same topics and receives these messages which were sent during his disconnected phase.

Actual behavior

After the reconnect, the server acknowledges the session persistence and immediately sends the messages in his queue - before the client has time to resubscribe. Interestingly, the client acknowledges the messages, however, the onMessage callback is not fired.

image

I also tried other brokers but got the same behavior

To Reproduce

Reproducer code


val client = Mqtt5Client.builder()
        .serverHost(mqttBroker)
        .identifier(uuid)
        .automaticReconnectWithDefaultConfig()
        .buildAsync()

client.connectWith()
            .cleanStart(false)
            .keepAlive(30)
            .sessionExpiryInterval(300)
            .send()
            .whenComplete { ack, throwable ->
                if (throwable != null) {
                    onFailure.invoke()
                } else {
                    //Here we call subscribeWith()
                    onConnected.invoke()
                }
            }
// Ordinary disconnect
client.disconnectWith()
            .sessionExpiryInterval(300)
            .send()

Details

MicWalter commented 2 years ago

Hi @sirtoobii,

After the reconnect, the server acknowledges the session persistence and immediately sends the messages in his queue - before the client has time to resubscribe. Interestingly, the client acknowledges the messages

This is correct behaviour as you don't overwrite the session when you reconnect, so the server still has the clients session stored and therefore knows the clients current subscriptions and the clients queued messages (which he will send out as soon as the connection is established, as you can see from your Wireshark image).

however, the onMessage callback is not fired.

Can you please provide your code? This seems to be something that doesn't relate to the hivemq-mqtt-client code because there exists no onMessage() method.

Greetings, Michael from the HiveMQ team

SgtSilvio commented 2 years ago

In addition to what @MicWalter said: You can call subscribe before connect, so that the callback is already registered when the first queued messages arrive.

sirtoobii commented 2 years ago

Thank you very much for your help :)

Can you please provide your code? This seems to be something that doesn't relate to the hivemq-mqtt-client code because there exists no onMessage() method.

Well, I was a bit unspecific here, with onMessage() I meant the callback which is fired when a message is published to a subscribed topic...

You can call subscribe before connect, so that the callback is already registered when the first queued messages arrive.

This is exactly what I was looking for I wasn't aware of this and thought you can only subscribe when there is an active connection

SgtSilvio commented 2 years ago

I will close this issue, if you have additional questions, don't hesitate to comment or open a new issue