eclipse / paho.mqtt.rust

paho.mqtt.rust
Other
516 stars 102 forks source link

Provide control over PUBACK to the client #141

Open koepalex opened 2 years ago

koepalex commented 2 years ago

Would it be possible to let the (async) client control when the PUBACK for QOS1 is send and to allow the application to call ack with a message-id as explicit acknowledgements once it safely handled the message?

It is a similar ask like paho.mqtt.python#554 but for the rust crate. Maybe it is this already possible but I didn't saw it?

koepalex commented 2 years ago

Could someone explain what would be the changes (sources files) that are necessary to avoid auto PUBACK and send it explicitly?

ctron commented 2 years ago

Looks like this is possible with rumqtt: https://github.com/bytebeamio/rumqtt/blob/18c56c13c4a56ffcdb3a195806a311523856f925/rumqttc/examples/async_manual_acks.rs

fpagliughi commented 2 weeks ago

In my mind, the biggest problem with this is keeping compliant with the MQTT spec and making sure the user understands the implications.

First (from the latest v5 spec):

The Client MUST send PUBACK packets in the order in which the corresponding PUBLISH packets were received (QoS 1 messages) [MQTT-4.6.0-2] The Client MUST send PUBREC packets in the order in which the corresponding PUBLISH packets were received (QoS 2 messages) [MQTT-4.6.0-3] The Client MUST send PUBREL packets in the order in which the corresponding PUBREC packets were received (QoS 2 messages) [MQTT-4.6.0-4]

So the library would need to track the order that messages were received (which is not necessarily the numerical value of the message ID), and then hold any out-of-order ACKs and then make sure that they were sent back in the proper order.

Any withheld ACK withheld by the application would stop all further ACKs. If you disconnect at that point, the ACKs from all the additional messages would have never reached the server, and on the next reconnect (assuming a persistent session) all the messages that the app thought it had ACK'ed would be re-transmit by the server. The library would have to keep the unsent ACKs as part of its session state and intercept those messages, or just pass them to the app to deal with.

In addition, MQTT v5 now explicitly limits re-sending messages to reconnects:

When a Client reconnects with Clean Start set to 0 and a session is present, both the Client and Server MUST resend any unacknowledged PUBLISH packets (where QoS > 0) and PUBREL packets using their original Packet Identifiers. This is the only circumstance where a Client or Server is REQUIRED to resend messages. Clients and Servers MUST NOT resend messages at any other time [MQTT-4.4.0-1].

(Emphasis added).

There is no way, for example like AMQP, to to NAK a message to requeue it.