use of software.amazon.awssdk.crt.mqtt.MqttMessage in project aws-greengrass-nucleus by aws-greengrass.
the class IotJobsClientWrapper method SubscribeToJobExecutionsChangedEvents.
@Override
public CompletableFuture<Integer> SubscribeToJobExecutionsChangedEvents(JobExecutionsChangedSubscriptionRequest request, QualityOfService qos, Consumer<JobExecutionsChangedEvent> handler, Consumer<Exception> exceptionHandler) {
if (request.thingName == null) {
CompletableFuture<Integer> result = new CompletableFuture();
result.completeExceptionally(new MqttException("JobExecutionsChangedSubscriptionRequest must have a non-null thingName"));
return result;
}
String topic = String.format(JOB_EXECUTIONS_CHANGED_TOPIC, request.thingName);
Consumer<MqttMessage> messageHandler = jobExecutionCbs.computeIfAbsent(new Pair<>(handler, exceptionHandler), (k) -> (message) -> {
try {
String payload = new String(message.getPayload(), StandardCharsets.UTF_8);
JobExecutionsChangedEvent response = this.gson.fromJson(payload, JobExecutionsChangedEvent.class);
handler.accept(response);
} catch (Exception e) {
if (exceptionHandler != null) {
exceptionHandler.accept(e);
}
}
});
return this.connection.subscribe(topic, qos, messageHandler);
}
use of software.amazon.awssdk.crt.mqtt.MqttMessage in project aws-greengrass-nucleus by aws-greengrass.
the class IotJobsClientWrapper method SubscribeToDescribeJobExecutionAccepted.
@Override
public CompletableFuture<Integer> SubscribeToDescribeJobExecutionAccepted(DescribeJobExecutionSubscriptionRequest request, QualityOfService qos, Consumer<DescribeJobExecutionResponse> handler, Consumer<Exception> exceptionHandler) {
if (request.jobId == null || request.thingName == null) {
CompletableFuture result = new CompletableFuture();
result.completeExceptionally(new MqttException("DescribeJobExecutionSubscriptionRequest must have a non-null jobId and a non-null thingName"));
return result;
}
String topic = String.format(JOB_DESCRIBE_ACCEPTED_TOPIC, request.thingName, request.jobId);
Consumer<MqttMessage> messageHandler = describeJobCbs.computeIfAbsent(new Pair<>(handler, exceptionHandler), (k) -> (message) -> {
try {
String payload = new String(message.getPayload(), StandardCharsets.UTF_8);
DescribeJobExecutionResponse response = this.gson.fromJson(payload, DescribeJobExecutionResponse.class);
handler.accept(response);
} catch (Exception e) {
if (exceptionHandler != null) {
exceptionHandler.accept(e);
}
}
});
return this.connection.subscribe(topic, qos, messageHandler);
}
use of software.amazon.awssdk.crt.mqtt.MqttMessage in project aws-greengrass-nucleus by aws-greengrass.
the class MqttClient method publishSingleSpoolerMessage.
@SuppressWarnings({ "PMD.AvoidCatchingThrowable", "PMD.PreserveStackTrace" })
protected CompletableFuture<Integer> publishSingleSpoolerMessage(AwsIotMqttClient connection) throws InterruptedException {
long id = -1L;
try {
id = spool.popId();
SpoolMessage spooledMessage = spool.getMessageById(id);
PublishRequest request = spooledMessage.getRequest();
MqttMessage m = new MqttMessage(request.getTopic(), request.getPayload());
long finalId = id;
return connection.publish(m, request.getQos(), request.isRetain()).whenComplete((packetId, throwable) -> {
// packetId is the SDK assigned ID. Ignore this and instead use the spooler ID
if (throwable == null) {
spool.removeMessageById(finalId);
logger.atTrace().kv("id", finalId).kv("topic", request.getTopic()).log("Successfully published message");
} else {
if (maxPublishRetryCount == -1 || spooledMessage.getRetried().getAndIncrement() < maxPublishRetryCount) {
spool.addId(finalId);
logger.atError().log("Failed to publish the message via Spooler and will retry", throwable);
} else {
logger.atError().log("Failed to publish the message via Spooler" + " after retried {} times and will drop the message", maxPublishRetryCount, throwable);
}
}
});
} catch (Throwable t) {
// valid id is starting from 0
if (id >= 0) {
spool.addId(id);
}
if (Utils.getUltimateCause(t) instanceof InterruptedException) {
throw new InterruptedException("Interrupted while publishing from spooler");
}
CompletableFuture<Integer> fut = new CompletableFuture<>();
fut.completeExceptionally(t);
return fut;
}
}
use of software.amazon.awssdk.crt.mqtt.MqttMessage in project aws-greengrass-nucleus by aws-greengrass.
the class MqttClientTest method GIVEN_incoming_message_WHEN_received_and_subscriber_throws_THEN_still_calls_remaining_subscriptions.
@Test
void GIVEN_incoming_message_WHEN_received_and_subscriber_throws_THEN_still_calls_remaining_subscriptions(ExtensionContext context) throws ExecutionException, InterruptedException, TimeoutException {
ignoreExceptionWithMessage(context, "Uncaught!");
MqttClient client = spy(new MqttClient(deviceConfiguration, (c) -> builder, ses, executorService));
AwsIotMqttClient mockIndividual = mock(AwsIotMqttClient.class);
when(mockIndividual.subscribe(any(), any())).thenReturn(CompletableFuture.completedFuture(0));
when(client.getNewMqttClient()).thenReturn(mockIndividual);
assertFalse(client.connected());
client.subscribe(SubscribeRequest.builder().topic("A/B/+").callback((m) -> {
throw new RuntimeException("Uncaught!");
}).build());
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abc = asyncAssertOnConsumer((m) -> {
assertEquals("A/B/C", m.getTopic());
});
client.subscribe(SubscribeRequest.builder().topic("A/B/C").callback(abc.getRight()).build());
Consumer<MqttMessage> handler = client.getMessageHandlerForClient(mockIndividual);
handler.accept(new MqttMessage("A/B/C", new byte[0]));
abc.getLeft().get(0, TimeUnit.SECONDS);
}
use of software.amazon.awssdk.crt.mqtt.MqttMessage in project aws-greengrass-nucleus by aws-greengrass.
the class MqttClientTest method GIVEN_incoming_message_WHEN_received_THEN_subscribers_are_called.
@Test
void GIVEN_incoming_message_WHEN_received_THEN_subscribers_are_called() throws ExecutionException, InterruptedException, TimeoutException {
MqttClient client = spy(new MqttClient(deviceConfiguration, (c) -> builder, ses, executorService));
AwsIotMqttClient mockIndividual = mock(AwsIotMqttClient.class);
when(mockIndividual.subscribe(any(), any())).thenReturn(CompletableFuture.completedFuture(0));
when(client.getNewMqttClient()).thenReturn(mockIndividual);
assertFalse(client.connected());
// Subscribe with wildcard first so that that is the active cloud subscription.
// Then subscribe to 2 other topics which are included in the wildcard.
// Then show that each subscription here is called only for the topic that it
// subscribed to.
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abPlus = asyncAssertOnConsumer((m) -> {
assertThat(m.getTopic(), either(is("A/B/C")).or(is("A/B/D")));
}, 2);
client.subscribe(SubscribeRequest.builder().topic("A/B/+").callback(abPlus.getRight()).build());
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abc = asyncAssertOnConsumer((m) -> {
assertEquals("A/B/C", m.getTopic());
}, 2);
client.subscribe(SubscribeRequest.builder().topic("A/B/C").callback(abc.getRight()).build());
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abd = asyncAssertOnConsumer((m) -> {
assertEquals("A/B/D", m.getTopic());
});
client.subscribe(SubscribeRequest.builder().topic("A/B/D").callback(abd.getRight()).build());
Consumer<MqttMessage> handler = client.getMessageHandlerForClient(mockIndividual);
handler.accept(new MqttMessage("A/B/C", new byte[0]));
handler.accept(new MqttMessage("A/B/D", new byte[0]));
// No subscribers for this one
handler.accept(new MqttMessage("A/X/Y", new byte[0]));
abPlus.getLeft().get(0, TimeUnit.SECONDS);
abd.getLeft().get(0, TimeUnit.SECONDS);
// Ensure, that even after removing the wildcard subscription, the other topics still get
// messages
client.unsubscribe(UnsubscribeRequest.builder().topic("A/B/+").callback(abPlus.getRight()).build());
handler.accept(new MqttMessage("A/B/C", new byte[0]));
abc.getLeft().get(0, TimeUnit.SECONDS);
}
Aggregations