public static <SuccessT, PromiseT> BiConsumer<SuccessT, ? super Throwable> asyncPromiseNotifyingBiConsumer(
      BiConsumer<SuccessT, Promise<PromiseT>> successConsumer, Promise<PromiseT> promise) {
    return (success, fail) -> {
      if (fail != null) {
        promise.setFailure(fail);
      } else {
        try {
          successConsumer.accept(success, promise);
        } catch (Throwable e) {
          // If the successConsumer fails synchronously then we can notify the promise. If it fails asynchronously
          // it's up to the successConsumer to notify.
          promise.setFailure(e);
        }
      }
    };
  }
Creates a {@link BiConsumer} that notifies the promise of any failures either via the throwable passed into the BiConsumer
or as a result of running the successConsumer. This assumes that the successConsumer will notify the promise when it
completes successfully.

@param successConsumer BiConsumer to call if the result is successful. Promise is also passed and must be notified on
success.
@param promise Promise to notify.
@param <SuccessT> Success type.
@param <PromiseT> Type being fulfilled by the Promise.
@return BiConsumer that can be used in a {@link CompletableFuture#whenComplete(BiConsumer)} method.
ambry-commons/src/main/java/com/github/ambry/commons/NettyUtils.java