Search in sources :

Example 1 with RequestResponseClient

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));
    }));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) RequestResponseClient(org.eclipse.hono.client.RequestResponseClient) TestContext(io.vertx.ext.unit.TestContext) ProtonConnection(io.vertx.proton.ProtonConnection) Async(io.vertx.ext.unit.Async) BeforeClass(org.junit.BeforeClass) RunWith(org.junit.runner.RunWith) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Constants(org.eclipse.hono.util.Constants) InetAddress(java.net.InetAddress) ConnectionFactory(org.eclipse.hono.connection.ConnectionFactory) ProtonClientOptions(io.vertx.proton.ProtonClientOptions) MessageSender(org.eclipse.hono.client.MessageSender) Timeout(org.junit.rules.Timeout) RegistrationClient(org.eclipse.hono.client.RegistrationClient) AsyncResult(io.vertx.core.AsyncResult) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) Before(org.junit.Before) AfterClass(org.junit.AfterClass) Vertx(io.vertx.core.Vertx) Assert.assertTrue(org.junit.Assert.assertTrue) ServerErrorException(org.eclipse.hono.client.ServerErrorException) Test(org.junit.Test) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) Future(io.vertx.core.Future) TimeUnit(java.util.concurrent.TimeUnit) Mockito(org.mockito.Mockito) CountDownLatch(java.util.concurrent.CountDownLatch) Rule(org.junit.Rule) Handler(io.vertx.core.Handler) Async(io.vertx.ext.unit.Async) RegistrationClient(org.eclipse.hono.client.RegistrationClient) ProtonClientOptions(io.vertx.proton.ProtonClientOptions) Test(org.junit.Test)

Example 2 with RequestResponseClient

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")));
        }
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) RequestResponseClient(org.eclipse.hono.client.RequestResponseClient) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonDelivery(io.vertx.proton.ProtonDelivery) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) MessageConsumer(org.eclipse.hono.client.MessageConsumer) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Supplier(java.util.function.Supplier) Constants(org.eclipse.hono.util.Constants) Context(io.vertx.core.Context) ArrayList(java.util.ArrayList) ConnectionFactory(org.eclipse.hono.connection.ConnectionFactory) CredentialsClient(org.eclipse.hono.client.CredentialsClient) ProtonClientOptions(io.vertx.proton.ProtonClientOptions) TenantClient(org.eclipse.hono.client.TenantClient) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ConnectionFactoryBuilder(org.eclipse.hono.connection.ConnectionFactoryImpl.ConnectionFactoryBuilder) Map(java.util.Map) MessageSender(org.eclipse.hono.client.MessageSender) BiConsumer(java.util.function.BiConsumer) Message(org.apache.qpid.proton.message.Message) RegistrationClient(org.eclipse.hono.client.RegistrationClient) AsyncResult(io.vertx.core.AsyncResult) HonoClient(org.eclipse.hono.client.HonoClient) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) CacheProvider(org.eclipse.hono.cache.CacheProvider) Future(io.vertx.core.Future) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Handler(io.vertx.core.Handler) RequestResponseClient(org.eclipse.hono.client.RequestResponseClient) Handler(io.vertx.core.Handler) ServerErrorException(org.eclipse.hono.client.ServerErrorException)

Example 3 with RequestResponseClient

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);
    }
}
Also used : RequestResponseClient(org.eclipse.hono.client.RequestResponseClient)

Aggregations

RequestResponseClient (org.eclipse.hono.client.RequestResponseClient)3 AsyncResult (io.vertx.core.AsyncResult)2 Future (io.vertx.core.Future)2 Handler (io.vertx.core.Handler)2 Vertx (io.vertx.core.Vertx)2 ProtonClientOptions (io.vertx.proton.ProtonClientOptions)2 ProtonConnection (io.vertx.proton.ProtonConnection)2 HttpURLConnection (java.net.HttpURLConnection)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 TimeUnit (java.util.concurrent.TimeUnit)2 ClientErrorException (org.eclipse.hono.client.ClientErrorException)2 MessageSender (org.eclipse.hono.client.MessageSender)2 RegistrationClient (org.eclipse.hono.client.RegistrationClient)2 ServerErrorException (org.eclipse.hono.client.ServerErrorException)2 ClientConfigProperties (org.eclipse.hono.config.ClientConfigProperties)2 ConnectionFactory (org.eclipse.hono.connection.ConnectionFactory)2 Constants (org.eclipse.hono.util.Constants)2 Context (io.vertx.core.Context)1 Async (io.vertx.ext.unit.Async)1 TestContext (io.vertx.ext.unit.TestContext)1