https://github.com/elastic/elasticsearch/blob/099fb84cfcf87be6689c3516674f45438bafa767/server/src/main/java/org/elasticsearch/action/ActionListener.java#L420-L432

Rather than keeping hold of the `delegate` and using an `AtomicBoolean` to track the completion, we could use an `AtomicReference` and drop the whole listener on completion, which might free up heap in some fail-fast cases.
server/src/main/java/org/elasticsearch/action/ActionListener.java
private final BiConsumer<ActionListener<R>, T> bc;
        DelegatingFailureActionListener(ActionListener<R> delegate, BiConsumer<ActionListener<R>, T> bc) {
            super(delegate);
            this.bc = bc;
        }
        @Override
        public void onResponse(T t) {
            bc.accept(delegate, t);
        }
        @Override
        public String toString() {
            return super.toString() + "/" + bc;
        }
    }
    /**
     * Creates a listener that listens for a response (or failure) and executes the
     * corresponding runnable when the response (or failure) is received.
     *
     * @param runnable the runnable that will be called in event of success or failure
     * @param <Response> the type of the response
     * @return a listener that listens for responses and invokes the runnable when received
     */