private void checkAndMaybeComplete() {
    if (progressTracker.isDone()) {
      if (progressTracker.hasSucceeded()) {
        operationException.set(null);
      } else {
        if (operationTracker.hasFailedOnNotFound()) {
          operationException.set(new RouterException("GetBlobInfoOperation failed because of BlobNotFound",
              RouterErrorCode.BlobDoesNotExist));
        } else if (operationTracker.hasSomeUnavailability()) {
          setOperationException(
              new RouterException("GetBlobInfoOperation failed possibly because some replicas are unavailable",
                  RouterErrorCode.AmbryUnavailable));
        }
      }
      operationCompleted = true;
    }

    if (operationCompleted && operationCallbackInvoked.compareAndSet(false, true)) {
      if (QuotaUtils.postProcessCharge(quotaChargeCallback)) {
        try {
          quotaChargeCallback.checkAndCharge(false, true);
        } catch (QuotaException quotaException) {
          // No exception should be thrown when doing quota charge for blobinfo operation.
          logger.trace("Unexpected exception {} thrown on handling quota event for {}", quotaException, blobId);
        }
      }
      Exception e = operationException.get();
      if (operationResult == null && e == null) {
        e = new RouterException("Operation failed, but exception was not set", RouterErrorCode.UnexpectedInternalError);
        routerMetrics.operationFailureWithUnsetExceptionCount.inc();
      }
      if (e != null) {
        operationResult = null;
        routerMetrics.onGetBlobError(e, options, isEncrypted);
      }
      long operationLatencyMs = time.milliseconds() - submissionTimeMs;
      if (isEncrypted) {
        routerMetrics.getEncryptedBlobInfoOperationLatencyMs.update(operationLatencyMs);
      } else {
        routerMetrics.getBlobInfoOperationLatencyMs.update(operationLatencyMs);
      }
      nonBlockingRouter.completeOperation(null, getOperationCallback, operationResult, e);
    }
  }
Check whether the operation can be completed, if so complete it.
ambry-router/src/main/java/com/github/ambry/router/GetBlobInfoOperation.java