@ Override public Future < Channel > create ( final Promise < Channel > channelReadyPromise ) { final long delay = this . currentDelaySeconds . get ( ) ; channelReadyPromise . addListener ( new GenericFutureListener < Future < Channel > > ( ) { @ Override public void operationComplete ( final Future < Channel > future ) { final long updatedDelay = future . isSuccess ( ) ? 0 : Math . max ( Math . min ( delay * 2 , MAX_CONNECT_DELAY_SECONDS ) , MIN_CONNECT_DELAY_SECONDS ) ; ApnsChannelFactory . this . currentDelaySeconds . compareAndSet ( delay , updatedDelay ) ; } } ) ; this . bootstrapTemplate . config ( ) . group ( ) . schedule ( new Runnable ( ) { @ Override public void run ( ) { final Bootstrap bootstrap = ApnsChannelFactory . this . bootstrapTemplate . clone ( ) . channelFactory ( new AugmentingReflectiveChannelFactory <> ( ClientChannelClassUtil . getSocketChannelClass ( ApnsChannelFactory . this . bootstrapTemplate . config ( ) . group ( ) ) , CHANNEL_READY_PROMISE_ATTRIBUTE_KEY , channelReadyPromise ) ) ; final ChannelFuture connectFuture = bootstrap . connect ( ) ; connectFuture . addListener ( new GenericFutureListener < ChannelFuture > ( ) { @ Override public void operationComplete ( final ChannelFuture future ) { if ( ! future . isSuccess ( ) ) { // 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. tryFailureAndLogRejectedCause ( channelReadyPromise , future . cause ( ) ) ; } } } ) ; connectFuture . channel ( ) . closeFuture ( ) . addListener ( new GenericFutureListener < ChannelFuture > ( ) { @ Override public void operationComplete ( final ChannelFuture future ) { // We always want to try to fail the "channel ready" promise if the connection closes; if it has // already succeeded, this will have no effect. channelReadyPromise . tryFailure ( new IllegalStateException ( "Channel closed before HTTP/2 preface completed." ) ) ; } } ) ; } } , delay , TimeUnit . SECONDS ) ; return channelReadyPromise ; }
Creates and connects a new channel . The initial connection attempt may be delayed to accommodate exponential back - off requirements .