Search in sources :

Example 16 with Future

use of io.netty.util.concurrent.Future in project jersey by jersey.

the class NettyHttpContainerProvider method createServer.

/**
     * Create and start Netty server.
     *
     * @param baseUri       base uri.
     * @param configuration Jersey configuration.
     * @param sslContext    Netty SSL context (can be null).
     * @param block         when {@code true}, this method will block until the server is stopped. When {@code false}, the
     *                      execution will
     *                      end immediately after the server is started.
     * @return Netty channel instance.
     * @throws ProcessingException when there is an issue with creating new container.
     */
public static Channel createServer(final URI baseUri, final ResourceConfig configuration, SslContext sslContext, final boolean block) throws ProcessingException {
    // Configure the server.
    final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    final EventLoopGroup workerGroup = new NioEventLoopGroup();
    final NettyHttpContainer container = new NettyHttpContainer(configuration);
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.option(ChannelOption.SO_BACKLOG, 1024);
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new JerseyServerInitializer(baseUri, sslContext, container));
        int port = getPort(baseUri);
        Channel ch = b.bind(port).sync().channel();
        ch.closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() {

            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                container.getApplicationHandler().onShutdown(container);
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        });
        if (block) {
            ch.closeFuture().sync();
            return ch;
        } else {
            return ch;
        }
    } catch (InterruptedException e) {
        throw new ProcessingException(e);
    }
}
Also used : NioServerSocketChannel(io.netty.channel.socket.nio.NioServerSocketChannel) NioServerSocketChannel(io.netty.channel.socket.nio.NioServerSocketChannel) Channel(io.netty.channel.Channel) ServerBootstrap(io.netty.bootstrap.ServerBootstrap) ProcessingException(javax.ws.rs.ProcessingException) EventLoopGroup(io.netty.channel.EventLoopGroup) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) Future(io.netty.util.concurrent.Future) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) ProcessingException(javax.ws.rs.ProcessingException)

Example 17 with Future

use of io.netty.util.concurrent.Future in project jersey by jersey.

the class JerseyHttp2ServerHandler method createContainerRequest.

/**
     * Create Jersey {@link ContainerRequest} based on Netty {@link HttpRequest}.
     *
     * @param ctx          Netty channel context.
     * @param http2Headers Netty Http/2 headers.
     * @return created Jersey Container Request.
     */
private ContainerRequest createContainerRequest(ChannelHandlerContext ctx, Http2HeadersFrame http2Headers) {
    String path = http2Headers.headers().path().toString();
    String s = path.startsWith("/") ? path.substring(1) : path;
    URI requestUri = URI.create(baseUri + ContainerUtils.encodeUnsafeCharacters(s));
    ContainerRequest requestContext = new ContainerRequest(baseUri, requestUri, http2Headers.headers().method().toString(), getSecurityContext(), new PropertiesDelegate() {

        private final Map<String, Object> properties = new HashMap<>();

        @Override
        public Object getProperty(String name) {
            return properties.get(name);
        }

        @Override
        public Collection<String> getPropertyNames() {
            return properties.keySet();
        }

        @Override
        public void setProperty(String name, Object object) {
            properties.put(name, object);
        }

        @Override
        public void removeProperty(String name) {
            properties.remove(name);
        }
    });
    // request entity handling.
    if (!http2Headers.isEndStream()) {
        ctx.channel().closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() {

            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                isList.add(NettyInputStream.END_OF_INPUT_ERROR);
            }
        });
        requestContext.setEntityStream(new NettyInputStream(isList));
    } else {
        requestContext.setEntityStream(new InputStream() {

            @Override
            public int read() throws IOException {
                return -1;
            }
        });
    }
    // copying headers from netty request to jersey container request context.
    for (CharSequence name : http2Headers.headers().names()) {
        requestContext.headers(name.toString(), mapToString(http2Headers.headers().getAll(name)));
    }
    return requestContext;
}
Also used : HashMap(java.util.HashMap) NettyInputStream(org.glassfish.jersey.netty.connector.internal.NettyInputStream) ByteBufInputStream(io.netty.buffer.ByteBufInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) NettyInputStream(org.glassfish.jersey.netty.connector.internal.NettyInputStream) URI(java.net.URI) IOException(java.io.IOException) Collection(java.util.Collection) Future(io.netty.util.concurrent.Future) ContainerRequest(org.glassfish.jersey.server.ContainerRequest) PropertiesDelegate(org.glassfish.jersey.internal.PropertiesDelegate)

Example 18 with Future

use of io.netty.util.concurrent.Future in project jersey by jersey.

the class JerseyServerHandler method createContainerRequest.

/**
     * Create Jersey {@link ContainerRequest} based on Netty {@link HttpRequest}.
     *
     * @param ctx Netty channel context.
     * @param req Netty Http request.
     * @return created Jersey Container Request.
     */
private ContainerRequest createContainerRequest(ChannelHandlerContext ctx, HttpRequest req) {
    String s = req.uri().startsWith("/") ? req.uri().substring(1) : req.uri();
    URI requestUri = URI.create(baseUri + ContainerUtils.encodeUnsafeCharacters(s));
    ContainerRequest requestContext = new ContainerRequest(baseUri, requestUri, req.method().name(), getSecurityContext(), new PropertiesDelegate() {

        private final Map<String, Object> properties = new HashMap<>();

        @Override
        public Object getProperty(String name) {
            return properties.get(name);
        }

        @Override
        public Collection<String> getPropertyNames() {
            return properties.keySet();
        }

        @Override
        public void setProperty(String name, Object object) {
            properties.put(name, object);
        }

        @Override
        public void removeProperty(String name) {
            properties.remove(name);
        }
    });
    // request entity handling.
    if ((req.headers().contains(HttpHeaderNames.CONTENT_LENGTH) && HttpUtil.getContentLength(req) > 0) || HttpUtil.isTransferEncodingChunked(req)) {
        ctx.channel().closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() {

            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                isList.add(NettyInputStream.END_OF_INPUT_ERROR);
            }
        });
        requestContext.setEntityStream(new NettyInputStream(isList));
    } else {
        requestContext.setEntityStream(new InputStream() {

            @Override
            public int read() throws IOException {
                return -1;
            }
        });
    }
    // copying headers from netty request to jersey container request context.
    for (String name : req.headers().names()) {
        requestContext.headers(name, req.headers().getAll(name));
    }
    return requestContext;
}
Also used : HashMap(java.util.HashMap) ByteBufInputStream(io.netty.buffer.ByteBufInputStream) NettyInputStream(org.glassfish.jersey.netty.connector.internal.NettyInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) NettyInputStream(org.glassfish.jersey.netty.connector.internal.NettyInputStream) URI(java.net.URI) IOException(java.io.IOException) Collection(java.util.Collection) Future(io.netty.util.concurrent.Future) ContainerRequest(org.glassfish.jersey.server.ContainerRequest) PropertiesDelegate(org.glassfish.jersey.internal.PropertiesDelegate)

Example 19 with Future

use of io.netty.util.concurrent.Future in project riposte by Nike-Inc.

the class StreamingAsyncHttpClient method streamDownstreamCall.

/**
     * TODO: Fully document me.
     * <br/>
     * NOTE: The returned CompletableFuture will only be completed successfully if the connection to the downstream
     * server was successful and the initialRequestChunk was successfully written out. This has implications for
     * initialRequestChunk regarding releasing its reference count (i.e. calling {@link
     * io.netty.util.ReferenceCountUtil#release(Object)} and passing in initialRequestChunk). If the returned
     * CompletableFuture is successful it means initialRequestChunk's reference count will already be reduced by one
     * relative to when this method was called because it will have been passed to a successful {@link
     * ChannelHandlerContext#writeAndFlush(Object)} method call.
     * <p/>
     * Long story short - assume initialRequestChunk is an object with a reference count of x:
     * <ul>
     *     <li>
     *         If the returned CompletableFuture is successful, then when it completes successfully
     *         initialRequestChunk's reference count will be x - 1
     *     </li>
     *     <li>
     *         If the returned CompletableFuture is *NOT* successful, then when it completes initialRequestChunk's
     *         reference count will still be x
     *     </li>
     * </ul>
     */
public CompletableFuture<StreamingChannel> streamDownstreamCall(String downstreamHost, int downstreamPort, HttpRequest initialRequestChunk, boolean isSecureHttpsCall, boolean relaxedHttpsValidation, StreamingCallback callback, long downstreamCallTimeoutMillis, ChannelHandlerContext ctx) {
    CompletableFuture<StreamingChannel> streamingChannel = new CompletableFuture<>();
    initialRequestChunk.headers().set(HttpHeaders.Names.HOST, downstreamHost);
    boolean performSubSpanAroundDownstreamCalls = true;
    ObjectHolder<Long> beforeConnectionStartTimeNanos = new ObjectHolder<>();
    beforeConnectionStartTimeNanos.heldObject = System.nanoTime();
    // Create a connection to the downstream server.
    ChannelPool pool = getPooledChannelFuture(downstreamHost, downstreamPort);
    Future<Channel> channelFuture = pool.acquire();
    // Add a listener that kicks off the downstream call once the connection is completed.
    channelFuture.addListener(future -> {
        Pair<Deque<Span>, Map<String, String>> originalThreadInfo = null;
        try {
            originalThreadInfo = linkTracingAndMdcToCurrentThread(ctx);
            if (!future.isSuccess()) {
                try {
                    streamingChannel.completeExceptionally(new WrapperException("Unable to connect to downstream host: " + downstreamHost, future.cause()));
                } finally {
                    Channel ch = channelFuture.getNow();
                    if (ch != null) {
                        markChannelAsBroken(ch);
                        pool.release(ch);
                    }
                }
                return;
            }
            if (logger.isDebugEnabled()) {
                logger.debug("CONNECTION SETUP TIME NANOS: {}", (System.nanoTime() - beforeConnectionStartTimeNanos.heldObject));
            }
            if (performSubSpanAroundDownstreamCalls) {
                String spanName = getSubspanSpanName(initialRequestChunk.getMethod().name(), downstreamHost + ":" + downstreamPort + initialRequestChunk.getUri());
                if (Tracer.getInstance().getCurrentSpan() == null) {
                    Tracer.getInstance().startRequestWithRootSpan(spanName);
                } else {
                    Tracer.getInstance().startSubSpan(spanName, Span.SpanPurpose.CLIENT);
                }
            }
            Deque<Span> distributedSpanStackToUse = Tracer.getInstance().getCurrentSpanStackCopy();
            Map<String, String> mdcContextToUse = MDC.getCopyOfContextMap();
            Span spanForDownstreamCall = (distributedSpanStackToUse == null) ? null : distributedSpanStackToUse.peek();
            if (spanForDownstreamCall != null) {
                setHeaderIfValueNotNull(initialRequestChunk, TraceHeaders.TRACE_SAMPLED, String.valueOf(spanForDownstreamCall.isSampleable()));
                setHeaderIfValueNotNull(initialRequestChunk, TraceHeaders.TRACE_ID, spanForDownstreamCall.getTraceId());
                setHeaderIfValueNotNull(initialRequestChunk, TraceHeaders.SPAN_ID, spanForDownstreamCall.getSpanId());
                setHeaderIfValueNotNull(initialRequestChunk, TraceHeaders.PARENT_SPAN_ID, spanForDownstreamCall.getParentSpanId());
                setHeaderIfValueNotNull(initialRequestChunk, TraceHeaders.SPAN_NAME, spanForDownstreamCall.getSpanName());
            }
            Channel ch = channelFuture.getNow();
            if (logger.isDebugEnabled())
                logger.debug("Channel ID of the Channel pulled from the pool: {}", ch.toString());
            ch.eventLoop().execute(runnableWithTracingAndMdc(() -> {
                BiConsumer<String, Throwable> prepChannelErrorHandler = (errorMessage, cause) -> {
                    try {
                        streamingChannel.completeExceptionally(new WrapperException(errorMessage, cause));
                    } finally {
                        markChannelAsBroken(ch);
                        pool.release(ch);
                    }
                };
                try {
                    ObjectHolder<Boolean> callActiveHolder = new ObjectHolder<>();
                    callActiveHolder.heldObject = true;
                    ObjectHolder<Boolean> lastChunkSentDownstreamHolder = new ObjectHolder<>();
                    lastChunkSentDownstreamHolder.heldObject = false;
                    prepChannelForDownstreamCall(pool, ch, callback, distributedSpanStackToUse, mdcContextToUse, isSecureHttpsCall, relaxedHttpsValidation, performSubSpanAroundDownstreamCalls, downstreamCallTimeoutMillis, callActiveHolder, lastChunkSentDownstreamHolder);
                    logInitialRequestChunk(initialRequestChunk, downstreamHost, downstreamPort);
                    ChannelFuture writeFuture = ch.writeAndFlush(initialRequestChunk);
                    writeFuture.addListener(completedWriteFuture -> {
                        if (completedWriteFuture.isSuccess())
                            streamingChannel.complete(new StreamingChannel(ch, pool, callActiveHolder, lastChunkSentDownstreamHolder, distributedSpanStackToUse, mdcContextToUse));
                        else {
                            prepChannelErrorHandler.accept("Writing the first HttpRequest chunk to the downstream service failed.", completedWriteFuture.cause());
                            return;
                        }
                    });
                } catch (SSLException | NoSuchAlgorithmException | KeyStoreException ex) {
                    prepChannelErrorHandler.accept("Error setting up SSL context for downstream call", ex);
                    return;
                } catch (Throwable t) {
                    prepChannelErrorHandler.accept("An unexpected error occurred while prepping the channel pipeline for the downstream call", t);
                    return;
                }
            }, ctx));
        } catch (Throwable ex) {
            try {
                String errorMsg = "Error occurred attempting to send first chunk (headers/etc) downstream";
                Exception errorToFire = new WrapperException(errorMsg, ex);
                logger.warn(errorMsg, errorToFire);
                streamingChannel.completeExceptionally(errorToFire);
            } finally {
                Channel ch = channelFuture.getNow();
                if (ch != null) {
                    markChannelAsBroken(ch);
                    pool.release(ch);
                }
            }
        } finally {
            unlinkTracingAndMdcFromCurrentThread(originalThreadInfo);
        }
    });
    return streamingChannel;
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) AttributeKey(io.netty.util.AttributeKey) Span(com.nike.wingtips.Span) HttpHeaders(io.netty.handler.codec.http.HttpHeaders) DefaultThreadFactory(io.netty.util.concurrent.DefaultThreadFactory) ChannelInboundHandlerAdapter(io.netty.channel.ChannelInboundHandlerAdapter) HttpMessage(io.netty.handler.codec.http.HttpMessage) LoggerFactory(org.slf4j.LoggerFactory) TraceHeaders(com.nike.wingtips.TraceHeaders) Random(java.util.Random) KeyStoreException(java.security.KeyStoreException) AsyncNettyHelper.unlinkTracingAndMdcFromCurrentThread(com.nike.riposte.util.AsyncNettyHelper.unlinkTracingAndMdcFromCurrentThread) HttpObject(io.netty.handler.codec.http.HttpObject) HttpClientCodec(io.netty.handler.codec.http.HttpClientCodec) InetAddress(java.net.InetAddress) ChannelPromise(io.netty.channel.ChannelPromise) Map(java.util.Map) ThreadFactory(java.util.concurrent.ThreadFactory) SocketChannel(io.netty.channel.socket.SocketChannel) HttpObjectDecoder(io.netty.handler.codec.http.HttpObjectDecoder) HttpRequest(io.netty.handler.codec.http.HttpRequest) TrustManagerFactory(javax.net.ssl.TrustManagerFactory) DownstreamIdleChannelTimeoutException(com.nike.riposte.server.error.exception.DownstreamIdleChannelTimeoutException) ChannelHealthChecker(io.netty.channel.pool.ChannelHealthChecker) DownstreamChannelClosedUnexpectedlyException(com.nike.riposte.server.error.exception.DownstreamChannelClosedUnexpectedlyException) KeyStore(java.security.KeyStore) ChannelPipeline(io.netty.channel.ChannelPipeline) InetSocketAddress(java.net.InetSocketAddress) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) List(java.util.List) SSLException(javax.net.ssl.SSLException) AbstractChannelPoolHandler(io.netty.channel.pool.AbstractChannelPoolHandler) LogLevel(io.netty.handler.logging.LogLevel) DefaultHttpResponse(io.netty.handler.codec.http.DefaultHttpResponse) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) HttpObjectEncoder(io.netty.handler.codec.http.HttpObjectEncoder) DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) HttpResponse(io.netty.handler.codec.http.HttpResponse) ChannelPoolMap(io.netty.channel.pool.ChannelPoolMap) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) HttpRequestEncoder(io.netty.handler.codec.http.HttpRequestEncoder) DownstreamIdleChannelTimeoutHandler(com.nike.riposte.client.asynchttp.netty.downstreampipeline.DownstreamIdleChannelTimeoutHandler) ChannelOption(io.netty.channel.ChannelOption) LoggingHandler(io.netty.handler.logging.LoggingHandler) Tracer(com.nike.wingtips.Tracer) CompletableFuture(java.util.concurrent.CompletableFuture) Errors(io.netty.channel.unix.Errors) Deque(java.util.Deque) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) EpollSocketChannel(io.netty.channel.epoll.EpollSocketChannel) AsyncNettyHelper.linkTracingAndMdcToCurrentThread(com.nike.riposte.util.AsyncNettyHelper.linkTracingAndMdcToCurrentThread) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) InsecureTrustManagerFactory(io.netty.handler.ssl.util.InsecureTrustManagerFactory) BiConsumer(java.util.function.BiConsumer) EpollEventLoopGroup(io.netty.channel.epoll.EpollEventLoopGroup) HttpContent(io.netty.handler.codec.http.HttpContent) Attribute(io.netty.util.Attribute) Logger(org.slf4j.Logger) EventLoopGroup(io.netty.channel.EventLoopGroup) CombinedChannelDuplexHandler(io.netty.channel.CombinedChannelDuplexHandler) SslContext(io.netty.handler.ssl.SslContext) Promise(io.netty.util.concurrent.Promise) HostnameResolutionException(com.nike.riposte.server.error.exception.HostnameResolutionException) Field(java.lang.reflect.Field) UnknownHostException(java.net.UnknownHostException) ChannelFuture(io.netty.channel.ChannelFuture) Epoll(io.netty.channel.epoll.Epoll) Consumer(java.util.function.Consumer) Channel(io.netty.channel.Channel) SimpleChannelPool(io.netty.channel.pool.SimpleChannelPool) Bootstrap(io.netty.bootstrap.Bootstrap) FullHttpResponse(io.netty.handler.codec.http.FullHttpResponse) WrapperException(com.nike.backstopper.exception.WrapperException) MDC(org.slf4j.MDC) SimpleChannelInboundHandler(io.netty.channel.SimpleChannelInboundHandler) NativeIoExceptionWrapper(com.nike.riposte.server.error.exception.NativeIoExceptionWrapper) AsyncNettyHelper.runnableWithTracingAndMdc(com.nike.riposte.util.AsyncNettyHelper.runnableWithTracingAndMdc) ChannelPool(io.netty.channel.pool.ChannelPool) SslContextBuilder(io.netty.handler.ssl.SslContextBuilder) ChannelHandler(io.netty.channel.ChannelHandler) Pair(com.nike.internal.util.Pair) AbstractChannelPoolMap(io.netty.channel.pool.AbstractChannelPoolMap) Future(io.netty.util.concurrent.Future) SimpleChannelPool(io.netty.channel.pool.SimpleChannelPool) ChannelPool(io.netty.channel.pool.ChannelPool) SocketChannel(io.netty.channel.socket.SocketChannel) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) EpollSocketChannel(io.netty.channel.epoll.EpollSocketChannel) Channel(io.netty.channel.Channel) Deque(java.util.Deque) Span(com.nike.wingtips.Span) KeyStoreException(java.security.KeyStoreException) DownstreamIdleChannelTimeoutException(com.nike.riposte.server.error.exception.DownstreamIdleChannelTimeoutException) DownstreamChannelClosedUnexpectedlyException(com.nike.riposte.server.error.exception.DownstreamChannelClosedUnexpectedlyException) SSLException(javax.net.ssl.SSLException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) HostnameResolutionException(com.nike.riposte.server.error.exception.HostnameResolutionException) UnknownHostException(java.net.UnknownHostException) WrapperException(com.nike.backstopper.exception.WrapperException) WrapperException(com.nike.backstopper.exception.WrapperException) CompletableFuture(java.util.concurrent.CompletableFuture) Map(java.util.Map) ChannelPoolMap(io.netty.channel.pool.ChannelPoolMap) AbstractChannelPoolMap(io.netty.channel.pool.AbstractChannelPoolMap) BiConsumer(java.util.function.BiConsumer)

Example 20 with Future

use of io.netty.util.concurrent.Future in project redisson by redisson.

the class BaseRemoteService method async.

private <T> T async(final Class<T> remoteInterface, final RemoteInvocationOptions options, final Class<?> syncInterface) {
    // local copy of the options, to prevent mutation
    final RemoteInvocationOptions optionsCopy = new RemoteInvocationOptions(options);
    final String toString = getClass().getSimpleName() + "-" + remoteInterface.getSimpleName() + "-proxy-" + generateRequestId();
    InvocationHandler handler = new InvocationHandler() {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("toString")) {
                return toString;
            } else if (method.getName().equals("equals")) {
                return proxy == args[0];
            } else if (method.getName().equals("hashCode")) {
                return toString.hashCode();
            }
            if (!optionsCopy.isResultExpected() && !(method.getReturnType().equals(Void.class) || method.getReturnType().equals(Void.TYPE) || method.getReturnType().equals(RFuture.class))) {
                throw new IllegalArgumentException("The noResult option only supports void return value");
            }
            final String requestId = generateRequestId();
            final String requestQueueName = getRequestQueueName(syncInterface);
            final String responseName = getResponseQueueName(syncInterface, requestId);
            final String ackName = getAckName(syncInterface, requestId);
            final RBlockingQueue<RemoteServiceRequest> requestQueue = redisson.getBlockingQueue(requestQueueName, getCodec());
            final RemoteServiceRequest request = new RemoteServiceRequest(requestId, method.getName(), getMethodSignatures(method), args, optionsCopy, System.currentTimeMillis());
            final RemotePromise<Object> result = new RemotePromise<Object>(commandExecutor.getConnectionManager().newPromise()) {

                @Override
                public boolean cancel(boolean mayInterruptIfRunning) {
                    if (isCancelled()) {
                        return true;
                    }
                    if (isDone()) {
                        return false;
                    }
                    if (optionsCopy.isAckExpected()) {
                        RFuture<Boolean> future = commandExecutor.evalWriteAsync(responseName, LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if redis.call('setnx', KEYS[1], 1) == 1 then " + "redis.call('pexpire', KEYS[1], ARGV[2]);" + "redis.call('lrem', KEYS[3], 1, ARGV[1]);" + "redis.call('pexpire', KEYS[2], ARGV[2]);" + "return 1;" + "end;" + "return 0;", Arrays.<Object>asList(ackName, responseName, requestQueueName), encode(request), request.getOptions().getAckTimeoutInMillis());
                        boolean ackNotSent = commandExecutor.get(future);
                        if (ackNotSent) {
                            super.cancel(mayInterruptIfRunning);
                            return true;
                        }
                        return cancel(syncInterface, requestId, request, mayInterruptIfRunning);
                    }
                    boolean removed = remove(requestQueue, request);
                    if (removed) {
                        super.cancel(mayInterruptIfRunning);
                        return true;
                    }
                    return cancel(syncInterface, requestId, request, mayInterruptIfRunning);
                }

                private boolean cancel(Class<?> remoteInterface, String requestId, RemoteServiceRequest request, boolean mayInterruptIfRunning) {
                    if (isCancelled()) {
                        return true;
                    }
                    if (isDone()) {
                        return false;
                    }
                    String canceRequestName = getCancelRequestQueueName(remoteInterface, requestId);
                    cancelExecution(optionsCopy, responseName, request, mayInterruptIfRunning, canceRequestName, this);
                    awaitUninterruptibly(60, TimeUnit.SECONDS);
                    return isCancelled();
                }
            };
            result.setRequestId(requestId);
            RFuture<Boolean> addFuture = addAsync(requestQueue, request, result);
            addFuture.addListener(new FutureListener<Boolean>() {

                @Override
                public void operationComplete(Future<Boolean> future) throws Exception {
                    if (!future.isSuccess()) {
                        result.tryFailure(future.cause());
                        return;
                    }
                    if (optionsCopy.isAckExpected()) {
                        final RBlockingQueue<RemoteServiceAck> responseQueue = redisson.getBlockingQueue(responseName, getCodec());
                        RFuture<RemoteServiceAck> ackFuture = responseQueue.pollAsync(optionsCopy.getAckTimeoutInMillis(), TimeUnit.MILLISECONDS);
                        ackFuture.addListener(new FutureListener<RemoteServiceAck>() {

                            @Override
                            public void operationComplete(Future<RemoteServiceAck> future) throws Exception {
                                if (!future.isSuccess()) {
                                    result.tryFailure(future.cause());
                                    return;
                                }
                                RemoteServiceAck ack = future.getNow();
                                if (ack == null) {
                                    RFuture<RemoteServiceAck> ackFutureAttempt = tryPollAckAgainAsync(optionsCopy, responseQueue, ackName);
                                    ackFutureAttempt.addListener(new FutureListener<RemoteServiceAck>() {

                                        @Override
                                        public void operationComplete(Future<RemoteServiceAck> future) throws Exception {
                                            if (!future.isSuccess()) {
                                                result.tryFailure(future.cause());
                                                return;
                                            }
                                            if (future.getNow() == null) {
                                                Exception ex = new RemoteServiceAckTimeoutException("No ACK response after " + optionsCopy.getAckTimeoutInMillis() + "ms for request: " + request);
                                                result.tryFailure(ex);
                                                return;
                                            }
                                            awaitResultAsync(optionsCopy, result, request, responseName, ackName);
                                        }
                                    });
                                } else {
                                    awaitResultAsync(optionsCopy, result, request, responseName);
                                }
                            }
                        });
                    } else {
                        awaitResultAsync(optionsCopy, result, request, responseName);
                    }
                }
            });
            return result;
        }
    };
    return (T) Proxy.newProxyInstance(remoteInterface.getClassLoader(), new Class[] { remoteInterface }, handler);
}
Also used : RBlockingQueue(org.redisson.api.RBlockingQueue) RemoteServiceAck(org.redisson.remote.RemoteServiceAck) FutureListener(io.netty.util.concurrent.FutureListener) Method(java.lang.reflect.Method) RFuture(org.redisson.api.RFuture) InvocationHandler(java.lang.reflect.InvocationHandler) RemoteServiceTimeoutException(org.redisson.remote.RemoteServiceTimeoutException) IOException(java.io.IOException) RemoteServiceAckTimeoutException(org.redisson.remote.RemoteServiceAckTimeoutException) RemoteInvocationOptions(org.redisson.api.RemoteInvocationOptions) RemoteServiceRequest(org.redisson.remote.RemoteServiceRequest) RFuture(org.redisson.api.RFuture) Future(io.netty.util.concurrent.Future) RemoteServiceAckTimeoutException(org.redisson.remote.RemoteServiceAckTimeoutException) RemotePromise(org.redisson.executor.RemotePromise)

Aggregations

Future (io.netty.util.concurrent.Future)49 FutureListener (io.netty.util.concurrent.FutureListener)29 RFuture (org.redisson.api.RFuture)22 ChannelFuture (io.netty.channel.ChannelFuture)15 ChannelFutureListener (io.netty.channel.ChannelFutureListener)11 Channel (io.netty.channel.Channel)10 ArrayList (java.util.ArrayList)10 IOException (java.io.IOException)9 Timeout (io.netty.util.Timeout)8 TimerTask (io.netty.util.TimerTask)8 AtomicReference (java.util.concurrent.atomic.AtomicReference)8 ScheduledFuture (io.netty.util.concurrent.ScheduledFuture)7 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)7 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)7 RedisException (org.redisson.client.RedisException)7 NioSocketChannel (io.netty.channel.socket.nio.NioSocketChannel)6 Collection (java.util.Collection)6 Test (org.junit.Test)6 RedisConnection (org.redisson.client.RedisConnection)6 RedisConnectionException (org.redisson.client.RedisConnectionException)6