@Override
    public void onCompletion(Long result, Exception exception) {
      long callbackReceiveTime = System.currentTimeMillis();
      if (callbackInvoked.compareAndSet(false, true)) {
        try {
          long callbackWaitTime = callbackReceiveTime - operationStartTime;
          metrics.responseCallbackWaitTimeInMs.update(callbackWaitTime);
          restRequest.getMetricsTracker().scalingMetricsTracker.addToResponseProcessingWaitTime(callbackWaitTime);
          inFlightResponsesCount.decrementAndGet();
          if (exception == null && (result == null || (response.getSize() != -1 && result != response.getSize()))) {
            exception = new IllegalStateException("Response write incomplete");
          }
          onResponseComplete(restRequest, restResponseChannel, response, exception);
        } finally {
          long callbackProcessingTime = System.currentTimeMillis() - callbackReceiveTime;
          metrics.responseCallbackProcessingTimeInMs.update(callbackProcessingTime);
          restRequest.getMetricsTracker().scalingMetricsTracker.addToResponseProcessingTime(callbackProcessingTime);
        }
      }
    }
A queued response represented by a {@link ReadableStreamChannel} that encapsulates the response and a
{@link RestResponseChannel} that provides a way to return the response to the client.
@param restRequest the {@link RestRequest} that encapsulates the request.
@param response the {@link ReadableStreamChannel} that encapsulates the response.
@param restResponseChannel the {@link RestResponseChannel} to use to send the response to the client.
ambry-rest/src/main/java/com/github/ambry/rest/AsyncRequestResponseHandler.java