redboltz / mqtt_cpp

Boost Software License 1.0
425 stars 106 forks source link

Offline message storing difficulty #447

Open redboltz opened 4 years ago

redboltz commented 4 years ago

I discussed offline message storing before. I searched issues but not found. Maybe the discussion is held at the comment on the some PR.

So let me explain what is the difficult point to support offline messaging. I've checked MQTT.js and paho(Java). And I sent some PRs to MQTT.js and merged. paho's offline publish doesn't work well, so far.

The problem seems to be not well recognized.

What is offline message storing

When the client is not connected to the broker, user can send message and the message is stored somewhare. The situation happens before the first connection and after disconnection.

Difficlut point

You may think that the solution is simple, just store the messages to the queue. Unfortunately, it is not so simple.

Consider the following scenario:

  1. connect with clean start false
  2. publish message1
  3. force_disconnect before puback is received
  4. re-connect with clean start false
  5. message1 should be resent just after connack is received.

It is not offline message sending. Just resending.

How about the following scenario:

  1. publish message1
  2. connect with clean start false
  3. message1 should be resent just after connack is received.

This is https://github.com/redboltz/mqtt_cpp/wiki/Offline-Publish currently supported. Publish at the step1 is considered "send message but not received puback" message. I think that it is reasonable.

Consider

  1. connect with clean start false
  2. force_disconnect before puback is received
  3. publish message1
  4. re-connect with clean start false
  5. message1 should be resent just after connack is received.

In this case, publish at step3 is offline publish. Step2 disconnection might happen from the broker side. So we can't recognize the publish message is offline publish or sent online but puback is not received message. The expected behavior is both message should be resent. So we can treat them as the same type of message. *1

Let's consider expanded (not implemented) offline message storing functionality.

  1. subscribe
  2. publish *1
  3. connect with clean start false
  4. *1 message should be resent just after connack is received.
  5. subscribe message should be sent.

The important point is publish message is send before subscribe message. Because publish but puback not received message should be resent just after connack is received. It is defined by MQTT spec. If Step 1 and 2 set the same topic, then the message is not delivered because . It is expected behavior. So we can't use the simple queue.

Possible implementation I just come up with is if the message is publish with QoS1/2, then use existing store mechanism. Otherwise insert newly added queue. The problem is publish with QoS0. Publish order interleaving seems to wrong.

This is difficulty.

redboltz commented 4 years ago

In addition mqtt_cpp has https://github.com/redboltz/mqtt_cpp/wiki/Persistence functionality. If the publish message should be stored, then call persistent handler. This functionality should be integrated well with offline message storing.