use of io.vertx.core.Future in project hono by eclipse.
the class BaseTenantService method processAddRequest.
private Future<EventBusMessage> processAddRequest(final EventBusMessage request) {
final String tenantId = request.getTenant();
final JsonObject payload = getRequestPayload(request.getJsonPayload());
if (tenantId == null) {
log.debug("request does not contain mandatory property [{}]", MessageHelper.APP_PROPERTY_TENANT_ID);
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
} else if (isValidRequestPayload(payload)) {
log.debug("creating tenant [{}]", tenantId);
final Future<TenantResult<JsonObject>> addResult = Future.future();
addNotPresentFieldsWithDefaultValuesForTenant(payload);
add(tenantId, payload, addResult.completer());
return addResult.map(tr -> {
return request.getResponse(tr.getStatus()).setJsonPayload(tr.getPayload()).setCacheDirective(tr.getCacheDirective());
});
} else {
log.debug("request contains malformed payload");
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
}
}
use of io.vertx.core.Future in project hono by eclipse.
the class BaseTenantService method processGetRequest.
private Future<EventBusMessage> processGetRequest(final EventBusMessage request) {
final String tenantId = request.getTenant();
final JsonObject payload = request.getJsonPayload();
if (tenantId == null && payload == null) {
log.debug("request does not contain any query parameters");
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
} else if (payload != null) {
final String tenantIdFromPayload = getTypesafeValueForField(payload, TenantConstants.FIELD_PAYLOAD_TENANT_ID);
if (tenantIdFromPayload == null) {
log.debug("payload does not contain any query parameters");
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
} else {
log.debug("retrieving tenant [id: {}]", tenantIdFromPayload);
final Future<TenantResult<JsonObject>> getResult = Future.future();
get(tenantIdFromPayload, getResult.completer());
return getResult.map(tr -> {
return request.getResponse(tr.getStatus()).setJsonPayload(tr.getPayload()).setTenant(tenantIdFromPayload).setCacheDirective(tr.getCacheDirective());
});
}
} else {
// deprecated API
log.debug("retrieving tenant [{}] using deprecated variant of get tenant request", tenantId);
final Future<TenantResult<JsonObject>> getResult = Future.future();
get(tenantId, getResult.completer());
return getResult.map(tr -> {
return request.getResponse(tr.getStatus()).setJsonPayload(tr.getPayload()).setTenant(tenantId).setCacheDirective(tr.getCacheDirective());
});
}
}
use of io.vertx.core.Future in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapter method uploadMessage.
private Future<Void> uploadMessage(final MqttContext ctx, final String tenant, final String deviceId, final Buffer payload, final Future<MessageSender> senderTracker, final String endpointName) {
if (payload.length() == 0) {
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "payload must not be empty"));
} else {
final Future<JsonObject> tokenTracker = getRegistrationAssertion(tenant, deviceId, ctx.authenticatedDevice());
final Future<TenantObject> tenantConfigTracker = getTenantConfiguration(tenant);
return CompositeFuture.all(tokenTracker, tenantConfigTracker, senderTracker).compose(ok -> {
if (tenantConfigTracker.result().isAdapterEnabled(getTypeName())) {
final Message downstreamMessage = newMessage(String.format("%s/%s", endpointName, tenant), deviceId, ctx.message().topicName(), ctx.contentType(), payload, tokenTracker.result());
customizeDownstreamMessage(downstreamMessage, ctx);
return senderTracker.result().send(downstreamMessage);
} else {
// this adapter is not enabled for the tenant
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN));
}
}).compose(delivery -> {
LOG.trace("successfully processed message [topic: {}, QoS: {}] for device [tenantId: {}, deviceId: {}]", ctx.message().topicName(), ctx.message().qosLevel(), tenant, deviceId);
metrics.incrementProcessedMqttMessages(endpointName, tenant);
onMessageSent(ctx);
// check that the remote MQTT client is still connected before sending PUBACK
if (ctx.deviceEndpoint().isConnected() && ctx.message().qosLevel() == MqttQoS.AT_LEAST_ONCE) {
ctx.deviceEndpoint().publishAcknowledge(ctx.message().messageId());
}
return Future.<Void>succeededFuture();
}).recover(t -> {
if (ClientErrorException.class.isInstance(t)) {
ClientErrorException e = (ClientErrorException) t;
LOG.debug("cannot process message for device [tenantId: {}, deviceId: {}, endpoint: {}]: {} - {}", tenant, deviceId, endpointName, e.getErrorCode(), e.getMessage());
} else {
LOG.debug("cannot process message for device [tenantId: {}, deviceId: {}, endpoint: {}]", tenant, deviceId, endpointName, t);
metrics.incrementUndeliverableMqttMessages(endpointName, tenant);
onMessageUndeliverable(ctx);
}
return Future.failedFuture(t);
});
}
}
use of io.vertx.core.Future in project hono by eclipse.
the class HonoClientImplTest method testGetOrCreateRequestResponseClientFailsIfInvokedConcurrently.
/**
* Verifies that a concurrent request to create a request-response client fails the given
* future for tracking the attempt.
*
* @param ctx The helper to use for running async tests.
*/
@Test
public void testGetOrCreateRequestResponseClientFailsIfInvokedConcurrently(final TestContext ctx) {
// GIVEN a client that already tries to create a registration client for "tenant"
final Async connected = ctx.async();
client.connect(new ProtonClientOptions()).setHandler(ctx.asyncAssertSuccess(ok -> connected.complete()));
connected.await();
client.getOrCreateRequestResponseClient("registration/tenant", () -> Future.future(), result -> {
});
// WHEN an additional, concurrent attempt is made to create a client for "tenant"
client.getOrCreateRequestResponseClient("registration/tenant", () -> {
ctx.fail("should not create concurrent client");
return Future.succeededFuture(mock(RegistrationClient.class));
}, ctx.<RequestResponseClient>asyncAssertFailure(t -> {
// THEN the concurrent attempt fails without any attempt being made to create another client
ctx.assertTrue(ServerErrorException.class.isInstance(t));
}));
}
use of io.vertx.core.Future in project hono by eclipse.
the class HonoClientImplTest method testGetOrCreateTelemetrySenderFailsIfInvokedConcurrently.
/**
* Verifies that a concurrent request to create a sender fails the given future for tracking the attempt.
*
* @param ctx The helper to use for running async tests.
*/
@Test
public void testGetOrCreateTelemetrySenderFailsIfInvokedConcurrently(final TestContext ctx) {
// GIVEN a client that already tries to create a telemetry sender for "tenant"
final Async connected = ctx.async();
client.connect(new ProtonClientOptions()).setHandler(ctx.asyncAssertSuccess(ok -> connected.complete()));
connected.await();
client.getOrCreateSender("telemetry/tenant", () -> Future.future());
// WHEN an additional, concurrent attempt is made to create a telemetry sender for "tenant"
client.getOrCreateSender("telemetry/tenant", () -> {
ctx.fail("should not create concurrent client");
return Future.succeededFuture(mock(MessageSender.class));
}).setHandler(ctx.asyncAssertFailure(t -> {
// THEN the concurrent attempt fails without any attempt being made to create another sender
ctx.assertTrue(ServerErrorException.class.isInstance(t));
}));
}
Aggregations