Example usage for io.netty.util.concurrent Future cause

List of usage examples for io.netty.util.concurrent Future cause

Introduction

In this page you can find the example usage for io.netty.util.concurrent Future cause.

Prototype

Throwable cause();

Source Link

Document

Returns the cause of the failed I/O operation if the I/O operation has failed.

Usage

From source file:com.linecorp.armeria.client.circuitbreaker.CircuitBreakerRemoteInvokerTest.java

License:Apache License

@Test
public void testExceptionFilter() throws Exception {
    FakeTicker ticker = new FakeTicker();
    int minimumRequestThreshold = 2;
    Duration circuitOpenWindow = Duration.ofSeconds(60);
    Duration counterSlidingWindow = Duration.ofSeconds(180);
    Duration counterUpdateInterval = Duration.ofMillis(1);
    Future<Object> failedFuture = failedFuture();

    // a filter that ignores all exception
    ExceptionFilter exceptionFilter = (cause) -> false;

    CircuitBreaker circuitBreaker = new CircuitBreakerBuilder(remoteServiceName)
            .minimumRequestThreshold(minimumRequestThreshold).circuitOpenWindow(circuitOpenWindow)
            .counterSlidingWindow(counterSlidingWindow).counterUpdateInterval(counterUpdateInterval)
            .exceptionFilter(exceptionFilter).ticker(ticker).build();

    RemoteInvoker remoteInvoker = mock(RemoteInvoker.class);
    // return failed future
    when(remoteInvoker.invoke(any(), any(), any(), any(), any(), any())).thenReturn(failedFuture);

    CircuitBreakerMapping mapping = (eventLoop1, uri, options1, codec1, method, args1) -> circuitBreaker;
    CircuitBreakerRemoteInvoker stub = new CircuitBreakerRemoteInvoker(remoteInvoker, mapping);

    // CLOSED// w ww  . j av a  2s  .  c  om
    for (int i = 0; i < minimumRequestThreshold + 1; i++) {
        Future<Object> future = stub.invoke(eventLoop, uri, options, codec, methodA(), args);
        // The future is `failedFuture` itself
        assertThat(future.isSuccess(), is(false));
        // This is not a CircuitBreakerException
        assertThat(future.cause(), is(not(instanceOf(FailFastException.class))));
        ticker.advance(Duration.ofMillis(1).toNanos());
    }

    // OPEN
    Future<Object> future1 = stub.invoke(eventLoop, uri, options, codec, methodA(), args);
    // The circuit is still CLOSED
    assertThat(future1.isSuccess(), is(false));
    assertThat(future1.cause(), is(not(instanceOf(FailFastException.class))));
}

From source file:com.linecorp.armeria.client.endpoint.dns.DnsEndpointGroup.java

License:Apache License

private void sendQueries() {
    if (stopped) {
        return;/*from  ww  w .  java2 s .  c o  m*/
    }

    final Future<List<DnsRecord>> future;
    final int numQuestions = questions.size();
    if (numQuestions == 1) {
        // Simple case of single query
        final DnsQuestion question = questions.get(0);
        logger.debug("{} Sending a DNS query", logPrefix);
        future = resolver.resolveAll(question);
    } else {
        // Multiple queries
        logger.debug("{} Sending DNS queries", logPrefix);
        @SuppressWarnings("unchecked")
        final Promise<List<DnsRecord>> aggregatedPromise = eventLoop.newPromise();
        final FutureListener<List<DnsRecord>> listener = new FutureListener<List<DnsRecord>>() {
            private final List<DnsRecord> records = new ArrayList<>();
            private int remaining = numQuestions;
            @Nullable
            private List<Throwable> causes;

            @Override
            public void operationComplete(Future<List<DnsRecord>> future) throws Exception {
                if (future.isSuccess()) {
                    final List<DnsRecord> records = future.getNow();
                    this.records.addAll(records);
                } else {
                    if (causes == null) {
                        causes = new ArrayList<>(numQuestions);
                    }
                    causes.add(future.cause());
                }

                if (--remaining == 0) {
                    if (!records.isEmpty()) {
                        aggregatedPromise.setSuccess(records);
                    } else {
                        final Throwable aggregatedCause;
                        if (causes == null) {
                            aggregatedCause = new EndpointGroupException("empty result returned by DNS server");
                        } else {
                            aggregatedCause = new EndpointGroupException("failed to receive DNS records");
                            for (Throwable c : causes) {
                                aggregatedCause.addSuppressed(c);
                            }
                        }
                        aggregatedPromise.setFailure(aggregatedCause);
                    }
                }
            }
        };

        questions.forEach(q -> resolver.resolveAll(q).addListener(listener));
        future = aggregatedPromise;
    }

    attemptsSoFar++;
    future.addListener(this::onDnsRecords);
}

From source file:com.linecorp.armeria.client.endpoint.dns.DnsEndpointGroup.java

License:Apache License

private void onDnsRecords(Future<? super List<DnsRecord>> future) {
    if (stopped) {
        if (future.isSuccess()) {
            @SuppressWarnings("unchecked")
            final List<DnsRecord> result = (List<DnsRecord>) future.getNow();
            result.forEach(ReferenceCountUtil::safeRelease);
        }/*w  w w  . j ava 2s .com*/
        return;
    }

    if (!future.isSuccess()) {
        // Failed. Try again with the delay given by Backoff.
        final long delayMillis = backoff.nextDelayMillis(attemptsSoFar);
        logger.warn("{} DNS query failed; retrying in {} ms (attempts so far: {}):", logPrefix, delayMillis,
                attemptsSoFar, future.cause());
        scheduledFuture = eventLoop.schedule(this::sendQueries, delayMillis, TimeUnit.MILLISECONDS);
        return;
    }

    // Reset the counter so that Backoff is reset.
    attemptsSoFar = 0;

    @SuppressWarnings("unchecked")
    final List<DnsRecord> records = (List<DnsRecord>) future.getNow();
    final long serverTtl = records.stream().mapToLong(DnsRecord::timeToLive).min().orElse(minTtl);
    final int effectiveTtl = (int) Math.max(Math.min(serverTtl, maxTtl), minTtl);

    try {
        setEndpoints(onDnsRecords(records, effectiveTtl));
    } catch (Throwable t) {
        logger.warn("{} Failed to process the DNS query result: {}", logPrefix, records, t);
    } finally {
        records.forEach(ReferenceCountUtil::safeRelease);
        scheduledFuture = eventLoop.schedule(this::sendQueries, effectiveTtl, TimeUnit.SECONDS);
    }
}

From source file:com.linecorp.armeria.client.http.HttpClientDelegate.java

License:Apache License

@Override
public HttpResponse execute(ClientRequestContext ctx, HttpRequest req) throws Exception {
    final Endpoint endpoint = ctx.endpoint().resolve().withDefaultPort(ctx.sessionProtocol().defaultPort());
    autoFillHeaders(ctx, endpoint, req);

    final PoolKey poolKey = new PoolKey(InetSocketAddress.createUnresolved(endpoint.host(), endpoint.port()),
            ctx.sessionProtocol());//from w  w w .java 2s  .c  o  m

    final EventLoop eventLoop = ctx.eventLoop();
    final Future<Channel> channelFuture = pool(eventLoop).acquire(poolKey);
    final DecodedHttpResponse res = new DecodedHttpResponse(eventLoop);

    if (channelFuture.isDone()) {
        if (channelFuture.isSuccess()) {
            Channel ch = channelFuture.getNow();
            invoke0(ch, ctx, req, res, poolKey);
        } else {
            res.close(channelFuture.cause());
        }
    } else {
        channelFuture.addListener((Future<Channel> future) -> {
            if (future.isSuccess()) {
                Channel ch = future.getNow();
                invoke0(ch, ctx, req, res, poolKey);
            } else {
                res.close(channelFuture.cause());
            }
        });
    }

    return res;
}

From source file:com.linecorp.armeria.client.HttpClientDelegate.java

License:Apache License

@Override
public HttpResponse execute(ClientRequestContext ctx, HttpRequest req) throws Exception {
    final Endpoint endpoint = ctx.endpoint().resolve(ctx).withDefaultPort(ctx.sessionProtocol().defaultPort());
    autoFillHeaders(ctx, endpoint, req);
    if (!sanitizePath(req)) {
        req.abort();/*from   w  w  w  .j av a2s.  com*/
        return HttpResponse.ofFailure(new IllegalArgumentException("invalid path: " + req.path()));
    }

    final EventLoop eventLoop = ctx.eventLoop();
    final PoolKey poolKey = new PoolKey(endpoint.host(), endpoint.ipAddr(), endpoint.port(),
            ctx.sessionProtocol());
    final Future<Channel> channelFuture = factory.pool(eventLoop).acquire(poolKey);
    final DecodedHttpResponse res = new DecodedHttpResponse(eventLoop);

    if (channelFuture.isDone()) {
        if (channelFuture.isSuccess()) {
            final Channel ch = channelFuture.getNow();
            invoke0(ch, ctx, req, res, poolKey);
        } else {
            res.close(channelFuture.cause());
        }
    } else {
        channelFuture.addListener((Future<Channel> future) -> {
            if (future.isSuccess()) {
                final Channel ch = future.getNow();
                invoke0(ch, ctx, req, res, poolKey);
            } else {
                res.close(channelFuture.cause());
            }
        });
    }

    return res;
}

From source file:com.linecorp.armeria.client.HttpRemoteInvoker.java

License:Apache License

@Override
public <T> Future<T> invoke(EventLoop eventLoop, URI uri, ClientOptions options, ClientCodec codec,
        Method method, Object[] args) throws Exception {

    requireNonNull(uri, "uri");
    requireNonNull(options, "options");
    requireNonNull(codec, "codec");
    requireNonNull(method, "method");

    final Scheme scheme = Scheme.parse(uri.getScheme());
    final SessionProtocol sessionProtocol = validateSessionProtocol(scheme.sessionProtocol());
    final InetSocketAddress remoteAddress = convertToSocketAddress(uri, sessionProtocol.isTls());

    final PoolKey poolKey = new PoolKey(remoteAddress, sessionProtocol);
    final Future<Channel> channelFuture = pool(eventLoop).acquire(poolKey);

    final Promise<T> resultPromise = eventLoop.newPromise();

    codec.prepareRequest(method, args, resultPromise);
    if (channelFuture.isSuccess()) {
        Channel ch = channelFuture.getNow();
        invoke0(codec, ch, method, args, options, resultPromise, poolKey);
    } else {/*from   w  w w  . j  a va  2  s.  c  o m*/
        channelFuture.addListener((Future<Channel> future) -> {
            if (future.isSuccess()) {
                Channel ch = future.getNow();
                invoke0(codec, ch, method, args, options, resultPromise, poolKey);
            } else {
                resultPromise.setFailure(channelFuture.cause());
            }
        });
    }

    return resultPromise;
}

From source file:com.linecorp.armeria.client.HttpRemoteInvoker.java

License:Apache License

static <T> void invoke0(ClientCodec codec, Channel channel, Method method, Object[] args, ClientOptions options,
        Promise<T> resultPromise, PoolKey poolKey) {

    final HttpSession session = HttpSessionHandler.get(channel);
    final SessionProtocol sessionProtocol = session.protocol();
    if (sessionProtocol == null) {
        resultPromise.setFailure(ClosedSessionException.INSTANCE);
        return;/*  w ww .j a  v a2 s.c  o m*/
    }

    final EncodeResult encodeResult = codec.encodeRequest(channel, sessionProtocol, method, args);
    if (encodeResult.isSuccess()) {
        ServiceInvocationContext ctx = encodeResult.invocationContext();
        Promise<FullHttpResponse> responsePromise = channel.eventLoop().newPromise();

        final Invocation invocation = new Invocation(ctx, options, responsePromise, encodeResult.content());
        //write request
        final ChannelFuture writeFuture = writeRequest(channel, invocation, ctx, options);
        writeFuture.addListener(fut -> {
            if (!fut.isSuccess()) {
                ctx.rejectPromise(responsePromise, fut.cause());
            } else {
                long responseTimeoutMillis = options.responseTimeoutPolicy().timeout(ctx);
                scheduleTimeout(channel, responsePromise, responseTimeoutMillis, false);
            }
        });

        //handle response
        if (responsePromise.isSuccess()) {
            decodeResult(codec, resultPromise, ctx, responsePromise.getNow());
        } else {
            responsePromise.addListener((Future<FullHttpResponse> future) -> {
                if (future.isSuccess()) {
                    decodeResult(codec, resultPromise, ctx, responsePromise.getNow());
                } else {
                    ctx.rejectPromise(resultPromise, future.cause());
                }
            });
        }
    } else {
        final Throwable cause = encodeResult.cause();
        if (!resultPromise.tryFailure(cause)) {
            logger.warn("Failed to reject an invocation promise ({}) with {}", resultPromise, cause, cause);
        }
    }

    if (!session.onRequestSent()) {
        // Can't send a request via the current session anymore; do not return the channel to the pool.
        return;
    }

    // Return the channel to the pool.
    final KeyedChannelPool<PoolKey> pool = KeyedChannelPool.findPool(channel);
    if (sessionProtocol.isMultiplex()) {
        pool.release(poolKey, channel);
    } else {
        resultPromise.addListener(fut -> pool.release(poolKey, channel));
    }
}

From source file:com.linecorp.armeria.client.pool.DefaultKeyedChannelPool.java

License:Apache License

private void notifyConnect(K key, Future<Channel> future, Promise<Channel> promise) {
    assert future.isDone();

    try {//from w  w w .  j  a  va 2s  . co  m
        if (future.isSuccess()) {
            Channel channel = future.getNow();
            channel.attr(KeyedChannelPoolUtil.POOL).set(this);
            channelPoolHandler.channelCreated(key, channel);
            channel.closeFuture().addListener(f -> channelPoolHandler.channelClosed(key, channel));
            promise.setSuccess(channel);
        } else {
            promise.setFailure(future.cause());
        }
    } catch (Exception e) {
        promise.setFailure(e);
    }
}

From source file:com.linecorp.armeria.client.tracing.TracingRemoteInvoker.java

License:Apache License

/**
 * Returns client side annotations that should be added to span.
 *///  w w  w. j  a  v a2 s  .  c  o  m
@SuppressWarnings("UnusedParameters")
protected <T> List<KeyValueAnnotation> annotations(URI uri, ClientOptions options, ClientCodec codec,
        Method method, Object[] args, @Nullable Future<? super T> result) {

    final KeyValueAnnotation clientUriAnnotation = KeyValueAnnotation.create("client.uri",
            uri.toString() + '#' + method.getName());

    if (result == null || !result.isDone()) {
        return Collections.singletonList(clientUriAnnotation);
    }

    final List<KeyValueAnnotation> annotations = new ArrayList<>(3);
    annotations.add(clientUriAnnotation);

    final String clientResultText = result.isSuccess() ? "success" : "failure";
    annotations.add(KeyValueAnnotation.create("client.result", clientResultText));

    if (result.cause() != null) {
        annotations.add(KeyValueAnnotation.create("client.cause", result.cause().toString()));
    }
    return annotations;
}

From source file:com.linecorp.armeria.server.tracing.TracingServiceInvocationHandler.java

License:Apache License

/**
 * Returns server side annotations that should be added to span.
 *//*from w w  w  .  j  av a 2  s .c  o  m*/
protected <T> List<KeyValueAnnotation> annotations(ServiceInvocationContext ctx, Future<? super T> result) {
    final List<KeyValueAnnotation> annotations = new ArrayList<>(5);

    final StringBuilder uriBuilder = new StringBuilder();
    uriBuilder.append(ctx.scheme() != null ? ctx.scheme().uriText() : "unknown");
    uriBuilder.append("://");
    uriBuilder.append(ctx.host() != null ? ctx.host() : "<unknown-host>");
    uriBuilder.append(ctx.path() != null ? ctx.path() : "/<unknown-path>");
    if (ctx.method() != null) {
        uriBuilder.append('#');
        uriBuilder.append(ctx.method());
    }
    annotations.add(KeyValueAnnotation.create("server.uri", uriBuilder.toString()));

    if (ctx.remoteAddress() != null) {
        annotations.add(KeyValueAnnotation.create("server.remote", ctx.remoteAddress().toString()));
    }

    if (ctx.localAddress() != null) {
        annotations.add(KeyValueAnnotation.create("server.local", ctx.localAddress().toString()));
    }

    if (result != null && result.isDone()) {
        final String resultText = result.isSuccess() ? "success" : "failure";
        annotations.add(KeyValueAnnotation.create("server.result", resultText));

        if (result.cause() != null) {
            annotations.add(KeyValueAnnotation.create("server.cause", result.cause().toString()));
        }
    }
    return annotations;
}