use of org.eclipse.hono.client.RequestResponseClient 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 org.eclipse.hono.client.RequestResponseClient in project hono by eclipse.
the class HonoClientImpl method getOrCreateRequestResponseClient.
/**
* Gets an existing or creates a new request-response client for a particular service.
*
* @param key The key to look-up the client by.
* @param clientSupplier A consumer for an attempt to create a new client.
* @param resultHandler The handler to inform about the outcome of the operation.
*/
void getOrCreateRequestResponseClient(final String key, final Supplier<Future<RequestResponseClient>> clientSupplier, final Handler<AsyncResult<RequestResponseClient>> resultHandler) {
context.runOnContext(get -> {
final RequestResponseClient client = activeRequestResponseClients.get(key);
if (client != null && client.isOpen()) {
LOG.debug("reusing existing client [target: {}]", key);
resultHandler.handle(Future.succeededFuture(client));
} else if (!creationLocks.computeIfAbsent(key, k -> Boolean.FALSE)) {
// register a handler to be notified if the underlying connection to the server fails
// so that we can fail the result handler passed in
final Handler<Void> connectionFailureHandler = connectionLost -> {
// remove lock so that next attempt to open a sender doesn't fail
creationLocks.remove(key);
resultHandler.handle(Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no connection to service")));
};
creationRequests.add(connectionFailureHandler);
creationLocks.put(key, Boolean.TRUE);
LOG.debug("creating new client for {}", key);
clientSupplier.get().setHandler(creationAttempt -> {
if (creationAttempt.succeeded()) {
LOG.debug("successfully created new client for {}", key);
activeRequestResponseClients.put(key, creationAttempt.result());
} else {
LOG.debug("failed to create new client for {}", key, creationAttempt.cause());
activeRequestResponseClients.remove(key);
}
creationLocks.remove(key);
creationRequests.remove(connectionFailureHandler);
resultHandler.handle(creationAttempt);
});
} else {
LOG.debug("already trying to create a client for {}", key);
resultHandler.handle(Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no connection to service")));
}
});
}
use of org.eclipse.hono.client.RequestResponseClient in project hono by eclipse.
the class HonoClientImpl method removeActiveRequestResponseClient.
private void removeActiveRequestResponseClient(final String targetAddress) {
final RequestResponseClient client = activeRequestResponseClients.remove(targetAddress);
if (client != null) {
client.close(s -> {
});
LOG.debug("closed and removed client for [{}]", targetAddress);
}
}
Aggregations