private void onComplete(UndeleteOperation op) {
    Exception e = op.getOperationException();
    if (e == null) {
      BlobId blobId = op.getBlobId();
      Pair<Account, Container> accountContainer =
          RouterUtils.getAccountContainer(accountService, blobId.getAccountId(), blobId.getContainerId());
      notificationSystem.onBlobUndeleted(op.getBlobId().getID(), op.getServiceId(), accountContainer.getFirst(),
          accountContainer.getSecond());
    } else {
      routerMetrics.onUndeleteBlobError(e);
    }
    routerMetrics.operationDequeuingRate.mark();
    routerMetrics.undeleteBlobOperationLatencyMs.update(time.milliseconds() - op.getOperationTimeMs());
    nonBlockingRouter.completeOperation(op.getFutureResult(), op.getCallback(), op.getOperationResult(),
        op.getOperationException());
  }
Called when the undelete operation is completed. The {@link UndeleteManager} also finishes the undelete
operation by performing the callback and notification.
@param op The {@link UndeleteOperation} that has completed.
ambry-router/src/main/java/com/github/ambry/router/UndeleteManager.java