List of usage examples for io.netty.util.concurrent FailedFuture FailedFuture
public FailedFuture(EventExecutor executor, Throwable cause)
From source file:com.relayrides.pushy.apns.ApnsClient.java
License:Open Source License
/** * <p>Connects to the given APNs gateway on the given port.</p> * * <p>Once an initial connection has been established and until the client has been explicitly disconnected via the * {@link ApnsClient#disconnect()} method, the client will attempt to reconnect automatically if the connection * closes unexpectedly. If the connection closes unexpectedly, callers may monitor the status of the reconnection * attempt with the {@code Future} returned by the {@link ApnsClient#getReconnectionFuture()} method.</p> * * @param host the APNs gateway to which to connect * @param port the port on which to connect to the APNs gateway * * @return a {@code Future} that will succeed when the client has connected to the gateway and is ready to send * push notifications// w ww. ja va2s . c o m * * @see ApnsClient#PRODUCTION_APNS_HOST * @see ApnsClient#DEVELOPMENT_APNS_HOST * @see ApnsClient#DEFAULT_APNS_PORT * @see ApnsClient#ALTERNATE_APNS_PORT * * @since 0.5 */ public Future<Void> connect(final String host, final int port) { final Future<Void> connectionReadyFuture; if (this.bootstrap.config().group().isShuttingDown() || this.bootstrap.config().group().isShutdown()) { connectionReadyFuture = new FailedFuture<>(GlobalEventExecutor.INSTANCE, new IllegalStateException( "Client's event loop group has been shut down and cannot be restarted.")); } else { synchronized (this.bootstrap) { // We only want to begin a connection attempt if one is not already in progress or complete; if we already // have a connection future, just return the existing promise. if (this.connectionReadyPromise == null) { this.metricsListener.handleConnectionAttemptStarted(this); final ChannelFuture connectFuture = this.bootstrap.connect(host, port); this.connectionReadyPromise = connectFuture.channel().newPromise(); connectFuture.addListener(new GenericFutureListener<ChannelFuture>() { @Override public void operationComplete(final ChannelFuture future) throws Exception { if (!future.isSuccess()) { final ChannelPromise connectionReadyPromise = ApnsClient.this.connectionReadyPromise; if (connectionReadyPromise != null) { // This may seem spurious, but our goal here is to accurately report the cause of // connection failure; if we just wait for connection closure, we won't be able to // tell callers anything more specific about what went wrong. connectionReadyPromise.tryFailure(future.cause()); } } } }); connectFuture.channel().closeFuture().addListener(new GenericFutureListener<ChannelFuture>() { @Override public void operationComplete(final ChannelFuture future) throws Exception { synchronized (ApnsClient.this.bootstrap) { if (ApnsClient.this.connectionReadyPromise != null) { // We always want to try to fail the "connection ready" promise if the connection // closes; if it has already succeeded, this will have no effect. ApnsClient.this.connectionReadyPromise.tryFailure(new IllegalStateException( "Channel closed before HTTP/2 preface completed.")); ApnsClient.this.connectionReadyPromise = null; } if (ApnsClient.this.reconnectionPromise != null) { log.debug("Disconnected. Next automatic reconnection attempt in {} seconds.", ApnsClient.this.reconnectDelaySeconds); ApnsClient.this.scheduledReconnectFuture = future.channel().eventLoop() .schedule(new Runnable() { @Override public void run() { log.debug("Attempting to reconnect."); ApnsClient.this.connect(host, port); } }, ApnsClient.this.reconnectDelaySeconds, TimeUnit.SECONDS); ApnsClient.this.reconnectDelaySeconds = Math.min( ApnsClient.this.reconnectDelaySeconds, MAX_RECONNECT_DELAY_SECONDS); } } } }); this.connectionReadyPromise.addListener(new GenericFutureListener<ChannelFuture>() { @Override public void operationComplete(final ChannelFuture future) throws Exception { if (future.isSuccess()) { synchronized (ApnsClient.this.bootstrap) { if (ApnsClient.this.reconnectionPromise != null) { log.info("Connection to {} restored.", future.channel().remoteAddress()); ApnsClient.this.reconnectionPromise.trySuccess(); } else { log.info("Connected to {}.", future.channel().remoteAddress()); } ApnsClient.this.reconnectDelaySeconds = INITIAL_RECONNECT_DELAY_SECONDS; ApnsClient.this.reconnectionPromise = future.channel().newPromise(); } ApnsClient.this.metricsListener.handleConnectionAttemptSucceeded(ApnsClient.this); } else { log.info("Failed to connect.", future.cause()); ApnsClient.this.metricsListener.handleConnectionAttemptFailed(ApnsClient.this); } } }); } connectionReadyFuture = this.connectionReadyPromise; } } return connectionReadyFuture; }
From source file:com.relayrides.pushy.apns.ApnsClient.java
License:Open Source License
/** * <p>Returns a {@code Future} that will succeed when the client has re-established a connection to the APNs gateway. * Callers may use this method to determine when it is safe to resume sending notifications after a send attempt * fails with a {@link ClientNotConnectedException}.</p> * * <p>If the client is already connected, the {@code Future} returned by this method will succeed immediately. If * the client was not previously connected (either because it has never been connected or because it was explicitly * disconnected via the {@link ApnsClient#disconnect()} method), the {@code Future} returned by this method will * fail immediately with an {@link IllegalStateException}.</p> * * @return a {@code Future} that will succeed when the client has established a connection to the APNs gateway * * @since 0.5//from w w w . j a v a 2s. c o m */ public Future<Void> getReconnectionFuture() { final Future<Void> reconnectionFuture; synchronized (this.bootstrap) { if (this.isConnected()) { reconnectionFuture = this.connectionReadyPromise.channel().newSucceededFuture(); } else if (this.reconnectionPromise != null) { // If we're not connected, but have a reconnection promise, we're in the middle of a reconnection // attempt. reconnectionFuture = this.reconnectionPromise; } else { // We're not connected and have no reconnection future, which means we've either never connected or have // explicitly disconnected. reconnectionFuture = new FailedFuture<>(GlobalEventExecutor.INSTANCE, new IllegalStateException("Client was not previously connected.")); } } return reconnectionFuture; }
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>// ww w .j ava 2 s.c o 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:org.restcomm.media.network.netty.NettyNetworkManagerTest.java
License:Open Source License
@SuppressWarnings({ "unchecked", "rawtypes" }) @Test/* w ww .j av a2 s .c om*/ public void testCloseAsyncFailure() { // given final EventLoopGroup eventLoopGroup = mock(EventLoopGroup.class); final Bootstrap bootstrap = PowerMockito.mock(Bootstrap.class); PowerMockito.when(bootstrap.group()).thenReturn(eventLoopGroup); final NettyNetworkManager networkManager = new NettyNetworkManager(bootstrap); final FutureCallback<Void> callback = mock(FutureCallback.class); final Exception exception = new RuntimeException("Testing purposes!"); this.eventExecutor = new DefaultEventExecutor(); final Future shutdownFuture = new FailedFuture<>(this.eventExecutor, exception); // when when(eventLoopGroup.shutdownGracefully(any(Long.class), any(Long.class), any(TimeUnit.class))) .thenReturn(shutdownFuture); networkManager.close(callback); // then verify(callback, timeout(100)).onFailure(exception); }