private void gracefullyWithDelay()

in zuul-core/src/main/java/com/netflix/netty/common/Http2ConnectionCloseHandler.java [164:221]


    private void gracefullyWithDelay(EventExecutor executor, Channel parent, ChannelPromise promise) {
        // See javadoc for explanation of why this may be disabled.
        boolean allowGracefulDelayed = ConnectionCloseChannelAttributes.allowGracefulDelayed(parent);
        if (!allowGracefulDelayed) {
            immediate(parent, promise);
            return;
        }

        if (!parent.isActive()) {
            promise.setSuccess();
            return;
        }

        // First send a 'graceful shutdown' GOAWAY frame.
        /*
        "A server that is attempting to gracefully shut down a connection SHOULD send an initial GOAWAY frame with
        the last stream identifier set to 231-1 and a NO_ERROR code. This signals to the client that a shutdown is
        imminent and that initiating further requests is prohibited."
          -- https://http2.github.io/http2-spec/#GOAWAY
         */
        DefaultHttp2GoAwayFrame goaway = new DefaultHttp2GoAwayFrame(Http2Error.NO_ERROR);
        goaway.setExtraStreamIds(Integer.MAX_VALUE);
        parent.writeAndFlush(goaway);
        LOG.debug(
                "gracefullyWithDelay: flushed initial go_away frame. channel={}",
                parent.id().asShortText());

        // In N secs time, throw an error that causes the http2 codec to send another GOAWAY frame
        // (this time with accurate lastStreamId) and then close the connection.
        int gracefulCloseDelay = ConnectionCloseChannelAttributes.gracefulCloseDelay(parent);
        executor.schedule(
                () -> {

                    // Check that the client hasn't already closed the connection (due to the earlier goaway we sent).
                    if (parent.isActive()) {
                        // NOTE - the netty Http2ConnectionHandler specifically does not send another goaway when we
                        // call
                        // channel.close() if one has already been sent .... so when we want more than one sent, we need
                        // to do it
                        // explicitly ourselves like this.
                        LOG.debug(
                                "gracefullyWithDelay: firing graceful_shutdown event to make netty send a final"
                                        + " go_away frame and then close connection. channel={}",
                                parent.id().asShortText());
                        Http2Exception h2e =
                                new Http2Exception(Http2Error.NO_ERROR, Http2Exception.ShutdownHint.GRACEFUL_SHUTDOWN);
                        parent.pipeline().fireExceptionCaught(h2e);

                        parent.close().addListener(future -> {
                            promise.setSuccess();
                        });
                    } else {
                        promise.setSuccess();
                    }
                },
                gracefulCloseDelay,
                TimeUnit.SECONDS);
    }