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/NotifyOnceListener.java
private final AtomicBoolean hasBeenCalled = new AtomicBoolean(false);
    protected abstract void innerOnResponse(Response response);
    protected abstract void innerOnFailure(Exception e);
    @Override
    public final void onResponse(Response response) {
        if (hasBeenCalled.compareAndSet(false, true)) {
            innerOnResponse(response);
        }
    }
    @Override
    public final void onFailure(Exception e) {
        if (hasBeenCalled.compareAndSet(false, true)) {
            innerOnFailure(e);
        }
    }
}