Example usage for io.netty.util.concurrent Promise tryFailure

List of usage examples for io.netty.util.concurrent Promise tryFailure

Introduction

In this page you can find the example usage for io.netty.util.concurrent Promise tryFailure.

Prototype

boolean tryFailure(Throwable cause);

Source Link

Document

Marks this future as a failure and notifies all listeners.

Usage

From source file:alluxio.network.netty.NettyRPC.java

License:Apache License

/**
 * Sends a request and waits for a response.
 *
 * @param context the netty RPC context//from ww  w .j ava2 s. c o m
 * @param request the RPC request
 * @return the RPC response
 */
public static ProtoMessage call(final NettyRPCContext context, ProtoMessage request) throws IOException {
    Channel channel = Preconditions.checkNotNull(context.getChannel());
    final Promise<ProtoMessage> promise = channel.eventLoop().newPromise();
    channel.pipeline().addLast(new RPCHandler(promise));
    channel.writeAndFlush(new RPCProtoMessage(request)).addListener((ChannelFuture future) -> {
        if (future.cause() != null) {
            future.channel().close();
            promise.tryFailure(future.cause());
        }
    });
    ProtoMessage message;
    try {
        message = promise.get(context.getTimeoutMs(), TimeUnit.MILLISECONDS);
    } catch (ExecutionException | TimeoutException e) {
        CommonUtils.closeChannel(channel);
        throw new IOException(e);
    } catch (InterruptedException e) {
        CommonUtils.closeChannel(channel);
        throw new RuntimeException(e);
    } finally {
        if (channel.isOpen()) {
            channel.pipeline().removeLast();
        }
    }
    if (message.isResponse()) {
        CommonUtils.unwrapResponseFrom(message.asResponse(), context.getChannel());
    }
    return message;
}

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

License:Apache License

private void initSession(SessionProtocol protocol, ChannelFuture connectFuture,
        Promise<Channel> sessionPromise) {
    assert connectFuture.isSuccess();

    final Channel ch = connectFuture.channel();
    final EventLoop eventLoop = ch.eventLoop();
    assert eventLoop.inEventLoop();

    final ScheduledFuture<?> timeoutFuture = eventLoop.schedule(() -> {
        if (sessionPromise.tryFailure(new SessionProtocolNegotiationException(protocol,
                "connection established, but session creation timed out: " + ch))) {
            ch.close();//from ww w . j ava 2  s.c  o  m
        }
    }, options.connectTimeoutMillis(), TimeUnit.MILLISECONDS);

    ch.pipeline().addLast(new HttpSessionHandler(this, ch, sessionPromise, timeoutFuture));
}

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;/*from  www  .ja v a 2s.com*/
    }

    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.HttpSessionChannelFactory.java

License:Apache License

private void initSession(SessionProtocol protocol, ChannelFuture connectFuture,
        Promise<Channel> sessionPromise) {
    assert connectFuture.isSuccess();

    final Channel ch = connectFuture.channel();
    final EventLoop eventLoop = ch.eventLoop();
    assert eventLoop.inEventLoop();

    final ScheduledFuture<?> timeoutFuture = eventLoop.schedule(() -> {
        if (sessionPromise.tryFailure(new SessionProtocolNegotiationException(protocol,
                "connection established, but session creation timed out: " + ch))) {
            ch.close();/*ww  w. j  a va2 s.  c o  m*/
        }
    }, connectTimeoutMillis, TimeUnit.MILLISECONDS);

    ch.pipeline().addLast(new HttpSessionHandler(this, ch, sessionPromise, timeoutFuture));
}

From source file:com.linecorp.armeria.common.RequestContext.java

License:Apache License

/**
 * Rejects the specified {@code promise} with the specified {@code cause}. If {@code promise} is done
 * already, this method logs a warning about the failure. Note that a {@link Promise} can be done already
 * even if you did not call this method in the following cases:
 * <ul>/*from  w  w w. j a  v a 2  s. c o  m*/
 *   <li>Invocation timeout - The invocation associated with the {@link Promise} has been timed out.</li>
 *   <li>User error - A service implementation called any of the following methods more than once:
 *     <ul>
 *       <li>{@link #resolvePromise(Promise, Object)}</li>
 *       <li>{@link #rejectPromise(Promise, Throwable)}</li>
 *       <li>{@link Promise#setSuccess(Object)}</li>
 *       <li>{@link Promise#setFailure(Throwable)}</li>
 *       <li>{@link Promise#cancel(boolean)}</li>
 *     </ul>
 *   </li>
 * </ul>
 */
@Deprecated
default void rejectPromise(Promise<?> promise, Throwable cause) {
    if (promise.tryFailure(cause)) {
        // Fulfilled successfully.
        return;
    }

    final Throwable firstCause = promise.cause();
    if (firstCause instanceof TimeoutException) {
        // Timed out already.
        return;
    }

    if (Exceptions.isExpected(cause)) {
        // The exception that was thrown after firstCause (often a transport-layer exception)
        // was a usual expected exception, not an error.
        return;
    }

    LoggerFactory.getLogger(RequestContext.class).warn("Failed to reject a completed promise ({}) with {}",
            promise, cause, cause);
}

From source file:com.linecorp.armeria.common.ServiceInvocationContext.java

License:Apache License

/**
 * Rejects the specified {@code promise} with the specified {@code cause}. If {@code promise} is done
 * already, this method logs a warning about the failure. Note that a {@link Promise} can be done already
 * even if you did not call this method in the following cases:
 * <ul>//from  w ww . jav  a2  s  . co m
 *   <li>Invocation timeout - The invocation associated with the {@link Promise} has been timed out.</li>
 *   <li>User error - A service implementation called any of the following methods more than once:
 *     <ul>
 *       <li>{@link #resolvePromise(Promise, Object)}</li>
 *       <li>{@link #rejectPromise(Promise, Throwable)}</li>
 *       <li>{@link Promise#setSuccess(Object)}</li>
 *       <li>{@link Promise#setFailure(Throwable)}</li>
 *       <li>{@link Promise#cancel(boolean)}</li>
 *     </ul>
 *   </li>
 * </ul>
 */
public void rejectPromise(Promise<?> promise, Throwable cause) {
    if (promise.tryFailure(cause)) {
        // Fulfilled successfully.
        return;
    }

    final Throwable firstCause = promise.cause();
    if (firstCause instanceof TimeoutException) {
        // Timed out already.
        return;
    }

    if (Exceptions.isExpected(cause)) {
        // The exception that was thrown after firstCause (often a transport-layer exception)
        // was a usual expected exception, not an error.
        return;
    }

    logger().warn("Failed to reject a completed promise ({}) with {}", promise, cause, cause);
}

From source file:com.linecorp.armeria.server.http.tomcat.TomcatServiceInvocationHandler.java

License:Apache License

@Override
public void invoke(ServiceInvocationContext ctx, Executor blockingTaskExecutor, Promise<Object> promise)
        throws Exception {

    final Adapter coyoteAdapter = connector().getProtocolHandler().getAdapter();
    if (coyoteAdapter == null) {
        // Tomcat is not configured / stopped.
        promise.tryFailure(new ServiceUnavailableException());
        return;/*from   www . j a  va 2 s.  c o  m*/
    }

    final Request coyoteReq = convertRequest(ctx);
    final Response coyoteRes = new Response();
    coyoteReq.setResponse(coyoteRes);
    coyoteRes.setRequest(coyoteReq);

    final ByteBuf resContent = ctx.alloc().ioBuffer();
    coyoteRes.setOutputBuffer(new OutputBufferImpl(resContent));

    blockingTaskExecutor.execute(() -> {
        if (promise.isDone()) {
            return;
        }

        ServiceInvocationContext.setCurrent(ctx);
        try {
            coyoteAdapter.service(coyoteReq, coyoteRes);
            ctx.resolvePromise(promise, convertResponse(coyoteRes, resContent));
        } catch (Throwable t) {
            ctx.rejectPromise(promise, t);
        } finally {
            ServiceInvocationContext.removeCurrent();
        }
    });
}

From source file:com.relayrides.pushy.apns.ApnsClient.java

License:Open Source License

/**
 * <p>Sends a push notification to the APNs gateway.</p>
 *
 * <p>This method returns a {@code Future} that indicates whether the notification was accepted or rejected by the
 * gateway. If the notification was accepted, it may be delivered to its destination device at some time in the
 * future, but final delivery is not guaranteed. Rejections should be considered permanent failures, and callers
 * should <em>not</em> attempt to re-send the notification.</p>
 *
 * <p>The returned {@code Future} may fail with an exception if the notification could not be sent. Failures to
 * <em>send</em> a notification to the gatewayi.e. those that fail with exceptionsshould generally be considered
 * non-permanent, and callers should attempt to re-send the notification when the underlying problem has been
 * resolved.</p>/*from   w w w .  j  a v a 2 s. co  m*/
 *
 * <p>In particular, attempts to send a notification when the client is not connected will fail with a
 * {@link ClientNotConnectedException}. If the client was previously connected and has not been explicitly
 * disconnected (via the {@link ApnsClient#disconnect()} method), the client will attempt to reconnect
 * automatically. Callers may wait for a reconnection attempt to complete by waiting for the {@code Future} returned
 * by the {@link ApnsClient#getReconnectionFuture()} method.</p>
 *
 * @param notification the notification to send to the APNs gateway
 *
 * @param <T> the type of notification to be sent
 *
 * @return a {@code Future} that will complete when the notification has been either accepted or rejected by the
 * APNs gateway
 *
 * @since 0.8
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public <T extends ApnsPushNotification> Future<PushNotificationResponse<T>> sendNotification(
        final T notification) {
    final Future<PushNotificationResponse<T>> responseFuture;
    final long notificationId = this.nextNotificationId.getAndIncrement();

    // Instead of synchronizing here, we keep a final reference to the connection ready promise. We can get away
    // with this because we're not changing the state of the connection or its promises. Keeping a reference ensures
    // we won't suddenly "lose" the channel and get a NullPointerException, but risks sending a notification after
    // things have shut down. In that case, though, the returned futures should fail quickly, and the benefit of
    // not synchronizing for every write seems worth it.
    final ChannelPromise connectionReadyPromise = this.connectionReadyPromise;

    if (connectionReadyPromise != null && connectionReadyPromise.isSuccess()
            && connectionReadyPromise.channel().isActive()) {
        final Channel channel = connectionReadyPromise.channel();
        final Promise<PushNotificationResponse<ApnsPushNotification>> responsePromise = new DefaultPromise(
                channel.eventLoop());

        channel.writeAndFlush(new PushNotificationAndResponsePromise(notification, responsePromise))
                .addListener(new GenericFutureListener<ChannelFuture>() {

                    @Override
                    public void operationComplete(final ChannelFuture future) throws Exception {
                        if (future.isSuccess()) {
                            ApnsClient.this.metricsListener.handleNotificationSent(ApnsClient.this,
                                    notificationId);
                        } else {
                            responsePromise.tryFailure(future.cause());
                        }
                    }
                });

        responseFuture = (Future) responsePromise;
    } else {
        log.debug("Failed to send push notification because client is not connected: {}", notification);
        responseFuture = new FailedFuture<>(GlobalEventExecutor.INSTANCE, NOT_CONNECTED_EXCEPTION);
    }

    responseFuture.addListener(new GenericFutureListener<Future<PushNotificationResponse<T>>>() {

        @Override
        public void operationComplete(final Future<PushNotificationResponse<T>> future) throws Exception {
            if (future.isSuccess()) {
                final PushNotificationResponse<T> response = future.getNow();

                if (response.isAccepted()) {
                    ApnsClient.this.metricsListener.handleNotificationAccepted(ApnsClient.this, notificationId);
                } else {
                    ApnsClient.this.metricsListener.handleNotificationRejected(ApnsClient.this, notificationId);
                }
            } else {
                ApnsClient.this.metricsListener.handleWriteFailure(ApnsClient.this, notificationId);
            }
        }
    });

    return responseFuture;
}

From source file:com.relayrides.pushy.apns.ApnsClientHandler.java

License:Open Source License

@Override
public void write(final ChannelHandlerContext context, final Object message, final ChannelPromise writePromise)
        throws Http2Exception {
    if (message instanceof PushNotificationAndResponsePromise) {
        final PushNotificationAndResponsePromise pushNotificationAndResponsePromise = (PushNotificationAndResponsePromise) message;

        final ApnsPushNotification pushNotification = pushNotificationAndResponsePromise.getPushNotification();

        if (this.responsePromises.containsKey(pushNotification)) {
            writePromise.tryFailure(new PushNotificationStillPendingException());
        } else {/*from  www . ja va  2  s.  co  m*/
            this.responsePromises.put(pushNotification,
                    pushNotificationAndResponsePromise.getResponsePromise());

            pushNotificationAndResponsePromise.getResponsePromise().addListener(
                    new GenericFutureListener<Future<PushNotificationResponse<ApnsPushNotification>>>() {

                        @Override
                        public void operationComplete(
                                final Future<PushNotificationResponse<ApnsPushNotification>> future) {
                            // Regardless of the outcome, when the response promise is finished, we want to remove it from
                            // the map of pending promises.
                            ApnsClientHandler.this.responsePromises.remove(pushNotification);
                        }
                    });

            this.write(context, pushNotification, writePromise);
        }
    } else if (message instanceof ApnsPushNotification) {
        final ApnsPushNotification pushNotification = (ApnsPushNotification) message;

        try {
            final int streamId = (int) this.nextStreamId;

            final Http2Headers headers = new DefaultHttp2Headers().method(HttpMethod.POST.asciiName())
                    .authority(this.authority).path(APNS_PATH_PREFIX + pushNotification.getToken())
                    .addInt(APNS_EXPIRATION_HEADER, pushNotification.getExpiration() == null ? 0
                            : (int) (pushNotification.getExpiration().getTime() / 1000));

            final String authenticationToken = this.apnsClient
                    .getAuthenticationTokenSupplierForTopic(pushNotification.getTopic()).getToken();
            headers.add(APNS_AUTHORIZATION_HEADER, "bearer " + authenticationToken);

            if (pushNotification.getCollapseId() != null) {
                headers.add(APNS_COLLAPSE_ID_HEADER, pushNotification.getCollapseId());
            }

            if (pushNotification.getPriority() != null) {
                headers.addInt(APNS_PRIORITY_HEADER, pushNotification.getPriority().getCode());
            }

            if (pushNotification.getTopic() != null) {
                headers.add(APNS_TOPIC_HEADER, pushNotification.getTopic());
            }

            final ChannelPromise headersPromise = context.newPromise();
            this.encoder().writeHeaders(context, streamId, headers, 0, false, headersPromise);
            log.trace("Wrote headers on stream {}: {}", streamId, headers);

            final ByteBuf payloadBuffer = context.alloc().ioBuffer(INITIAL_PAYLOAD_BUFFER_CAPACITY);
            payloadBuffer.writeBytes(pushNotification.getPayload().getBytes(StandardCharsets.UTF_8));

            final ChannelPromise dataPromise = context.newPromise();
            this.encoder().writeData(context, streamId, payloadBuffer, 0, true, dataPromise);
            log.trace("Wrote payload on stream {}: {}", streamId, pushNotification.getPayload());

            final PromiseCombiner promiseCombiner = new PromiseCombiner();
            promiseCombiner.addAll(headersPromise, dataPromise);
            promiseCombiner.finish(writePromise);

            writePromise.addListener(new GenericFutureListener<ChannelPromise>() {

                @Override
                public void operationComplete(final ChannelPromise future) throws Exception {
                    if (future.isSuccess()) {
                        ApnsClientHandler.this.pushNotificationsByStreamId.put(streamId, pushNotification);
                        ApnsClientHandler.this.authenticationTokensByStreamId.put(streamId,
                                authenticationToken);
                    } else {
                        log.trace("Failed to write push notification on stream {}.", streamId, future.cause());

                        final Promise<PushNotificationResponse<ApnsPushNotification>> responsePromise = ApnsClientHandler.this.responsePromises
                                .get(pushNotification);

                        if (responsePromise != null) {
                            responsePromise.tryFailure(future.cause());
                        } else {
                            log.error("Notification write failed, but no response promise found.");
                        }
                    }
                }
            });

            this.nextStreamId += 2;

            if (this.nextStreamId >= STREAM_ID_RESET_THRESHOLD) {
                // This is very unlikely, but in the event that we run out of stream IDs (the maximum allowed is
                // 2^31, per https://httpwg.github.io/specs/rfc7540.html#StreamIdentifiers), we need to open a new
                // connection. Just closing the context should be enough; automatic reconnection should take things
                // from there.
                context.close();
            }
        } catch (NoKeyForTopicException | SignatureException e) {
            writePromise.tryFailure(e);
        }

    } else {
        // This should never happen, but in case some foreign debris winds up in the pipeline, just pass it through.
        log.error("Unexpected object in pipeline: {}", message);
        context.write(message, writePromise);
    }
}

From source file:com.relayrides.pushy.apns.ApnsClientHandler.java

License:Open Source License

@Override
public void close(final ChannelHandlerContext context, final ChannelPromise promise) throws Exception {
    super.close(context, promise);

    final ClientNotConnectedException clientNotConnectedException = new ClientNotConnectedException(
            "Client disconnected unexpectedly.");

    for (final Promise<PushNotificationResponse<ApnsPushNotification>> responsePromise : this.responsePromises
            .values()) {/* www.j a va2 s  .c  om*/
        responsePromise.tryFailure(clientNotConnectedException);
    }

    this.responsePromises.clear();
}