MQTTメッセージを送信している時にネットワークが途切れた際など、Greengrassのログに以下のエラーが発生する場合があります。こちらのエラーを制御する方法が検索しても出てこなかったので、調べた内容を記載します。
/greengrass/v2/logs/greengrass.log
2023-03-16T09:40:10.941Z [ERROR] (Thread-4) com.aws.greengrass.mqttclient.MqttClient: Failed to publish the message via Spooler and will retry. {}
java.util.concurrent.CompletionException: software.amazon.awssdk.crt.mqtt.MqttException: Time limit between request and response has been exceeded.
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:331)
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:346)
at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:632)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2088)
at software.amazon.awssdk.crt.AsyncCallback$1.onFailure(AsyncCallback.java:32)
Caused by: software.amazon.awssdk.crt.mqtt.MqttException: Time limit between request and response has been exceeded.
結論
Greengrass nucleusの mqtt.operationTimeoutMs
で制御可能です。デフォルトは30秒です。
以下の公式ドキュメントには2023/03/16時点では記載が無いので自己責任で使ってください。
https://docs.aws.amazon.com/greengrass/v2/developerguide/greengrass-nucleus-component.html
調査内容
そもそも、このエラーですが、Nucleusの内部で使われているMQTTライブラリで出力されています。
aws-c-mqtt/source/mqtt.c
AWS_DEFINE_ERROR_INFO_MQTT(
AWS_ERROR_MQTT_TIMEOUT,
"Time limit between request and response has been exceeded."),
同リポジトリに説明もあります。これに合わせて設定すれば制御できそうです。
aws-c-mqtt/include/aws/mqtt/client.h
* protocol_operation_timeout_ms
* Timeout when waiting for the response to some operation requires response by protocol.
* Set to zero to disable timeout. Otherwise, the operation will fail with error
* AWS_ERROR_MQTT_TIMEOUT if no response is received within this amount of time after
* the packet is written to the socket. The timer is reset if the connection is interrupted.
* It applied to PUBLISH (QoS>0) and UNSUBSCRIBE now.
* Note: While the MQTT 3 specification states that a broker MUST respond,
* some brokers are known to ignore publish packets in exceptional circumstances
* (e.g. AWS IoT Core will not respond if the publish quota is exceeded).
ではGreengrassからどうやって設定するか、公式ドキュメントには無いのでコード見てみたら、該当の設定値と同名の設定がありました。
aws-greengrass-nucleus/src/main/java/com/aws/greengrass/mqttclient/MqttClient.java
static final String MQTT_OPERATION_TIMEOUT_KEY = "operationTimeoutMs";
static final int DEFAULT_MQTT_OPERATION_TIMEOUT = (int) Duration.ofSeconds(30).toMillis();