Skip to content

Commit e7ba4f2

Browse files
committed
update MQTT5 User Guide and FAQ with Manual Publish Acknowledgement info
1 parent 67ddca3 commit e7ba4f2

2 files changed

Lines changed: 66 additions & 0 deletions

File tree

documents/FAQ.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* [Where can I find MQTT 311 Samples?](#where-can-i-find-mqtt-311-samples)
1414
* [How can I improve the library size?](#how-can-i-improve-the-library-size)
1515
* [Certificate and Private Key Usage Across Different Versions of the SDK on macOS](#certificate-and-private-key-usage-across-different-versions-of-the-sdk-on-macos)
16+
* [Manual Publish Acknowledgement and QoS 1 Redelivery](#manual-publish-acknowledgement-and-qos-1-redelivery)
1617
* [I still have more questions about this sdk?](#i-still-have-more-questions-about-this-sdk)
1718

1819
### Where should I start?
@@ -176,6 +177,18 @@ For maximum control, build both CRT and SDK locally:
176177
### Certificate and Private Key Usage Across Different Versions of the SDK on macOS
177178
A certificate and private key pair cannot be shared on a macOS device between aws-iot-device-sdk-java-v2 v1.29.0 and other versions. In the update to v1.29.0 we migrated macOS from using Apple's deprecated Security Framework to SecItem API. In doing so, certificate and private keys are imported in a non-backwards compatible manner into the Apple Keychain.
178179

180+
### Manual Publish Acknowledgement and QoS 1 Redelivery
181+
182+
When using [manual publish acknowledgement](./MQTT5_Userguide.md#manual-publish-acknowledgement), there are two important behaviors to be aware of regarding QoS 1 message redelivery:
183+
184+
**Broker redelivery of unacknowledged publishes**
185+
186+
The AWS IoT broker will periodically resend unacknowledged QoS 1 PUBLISH packets. These redeliveries should be treated as duplicates even if the DUP flag in the PUBLISH packet is not set. If the manual publish acknowledgement is not acquired again for a redelivered packet, the acknowledgement will be sent automatically.
187+
188+
**Session resumption after disconnect/reconnect**
189+
190+
Upon a disconnect and reconnect of the MQTT5 client, if a session is resumed, any previously acquired acknowledgement handle is void. The broker will resend the unacknowledged PUBLISH packet, and the acknowledgement must be reacquired from that resent packet. If the resent packet is not handled for manual acknowledgement, the acknowledgement will be sent automatically.
191+
179192
### I still have more questions about this sdk?
180193

181194
* [Here](https://docs.aws.amazon.com/iot/latest/developerguide/what-is-aws-iot.html) are the AWS IoT Core docs for more details about IoT Core

documents/MQTT5_Userguide.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
+ [Publish](#publish)
2525
+ [Subscribe and Unsubscribe](#subscribe-and-unsubscribe)
2626
+ [MQTT5 Best Practices](#mqtt5-best-practices)
27+
* [Advanced Operations and Settings](#advanced-operations-and-settings)
28+
+ [Manual Publish Acknowledgement](#manual-publish-acknowledgement)
2729

2830
# Introduction
2931

@@ -564,3 +566,54 @@ Below are some best practices for the MQTT5 client that are recommended to follo
564566
* Make sure to always call `close()` when finished a MQTT5 client to avoid native resource leaks!
565567
* For [publish](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/Mqtt5Client.html#publish(software.amazon.awssdk.crt.mqtt5.packets.PublishPacket)), [subscribe](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/Mqtt5Client.html#subscribe(software.amazon.awssdk.crt.mqtt5.packets.SubscribePacket)), and [unsubscribe](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/Mqtt5Client.html#unsubscribe(software.amazon.awssdk.crt.mqtt5.packets.UnsubscribePacket)), make sure to check the reason codes in the ACK ([PubAckPacket](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/PubAckPacket.html), [SubAckPacket](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/SubAckPacket.html), and [UnsubAckPacket](https://awslabs.github.io/aws-crt-java/software/amazon/awssdk/crt/mqtt5/packets/UnsubAckPacket.html) respectively) to see if the operation actually succeeded.
566568
* You MUST NOT perform blocking operations on any callback, or you will cause a deadlock. For example: in the `onMessageReceived` callback, do not send a publish, and then wait for the future to complete within the callback. The Client cannot do work until your callback returns, so the thread will be stuck.
569+
570+
## Advanced Operations and Settings
571+
572+
### Manual Publish Acknowledgement
573+
574+
By default, the MQTT5 client automatically sends a PUBACK for every QoS 1 PUBLISH it receives, immediately after the `onMessageReceived` callback returns. Manual publish acknowledgement gives you control over when that PUBACK is sent, allowing you to defer acknowledgement until after your application has fully processed the message — for example, after persisting it to a database or forwarding it to another service.
575+
576+
To take manual control of the PUBACK, call `publishReturn.acquirePublishAcknowledgementControl()` **within** the `onMessageReceived` callback. This returns a `Mqtt5PublishAcknowledgementControlHandle` that you can store and use later to send the PUBACK by calling `client.invokePublishAcknowledgement()`.
577+
578+
**Important constraints:**
579+
* `acquirePublishAcknowledgementControl()` must be called within the `onMessageReceived` callback. Calling it outside the callback or after it returns will return `null`.
580+
* `acquirePublishAcknowledgementControl()` may only be called once per received PUBLISH. Subsequent calls will return `null`.
581+
* This is only relevant for QoS 1 messages. Calling it on a QoS 0 message will return `null`.
582+
* If `acquirePublishAcknowledgementControl()` is not called, the client will automatically send the PUBACK when the callback returns.
583+
584+
The following example shows how to acquire the acknowledgement handle within the callback and invoke it later:
585+
586+
~~~ java
587+
// A shared location to store the acknowledgement handle for later use
588+
final AtomicReference<Mqtt5PublishAcknowledgementControlHandle> pendingAck = new AtomicReference<>();
589+
590+
class MyPublishEvents implements Mqtt5ClientOptions.PublishEvents {
591+
@Override
592+
public void onMessageReceived(Mqtt5Client client, PublishReturn publishReturn) {
593+
System.out.println("Message received on topic: " +
594+
publishReturn.getPublishPacket().getTopic());
595+
596+
if (publishReturn.getPublishPacket().getQOS() == QOS.AT_LEAST_ONCE) {
597+
// Acquire manual control of the PUBACK for this QoS 1 message.
598+
// This must be called within the callback. Calling it outside the callback
599+
// or after it returns will return null.
600+
Mqtt5PublishAcknowledgementControlHandle handle =
601+
publishReturn.acquirePublishAcknowledgementControl();
602+
603+
if (handle != null) {
604+
// The PUBACK will NOT be sent automatically because we acquired the handle.
605+
// Store it for later use after processing is complete.
606+
pendingAck.set(handle);
607+
}
608+
}
609+
}
610+
}
611+
612+
// ... build client, connect, and subscribe ...
613+
614+
// After processing is complete, send the PUBACK by invoking the acknowledgement.
615+
Mqtt5PublishAcknowledgementControlHandle handle = pendingAck.getAndSet(null);
616+
if (handle != null) {
617+
client.invokePublishAcknowledgement(handle);
618+
}
619+
~~~

0 commit comments

Comments
 (0)