@Override
  public Future<Void> updateBlobTtl(RestRequest restRequest, String blobId, String serviceId, long expiresAtMs,
      Callback<Void> callback, QuotaChargeCallback quotaChargeCallback) {
    FutureResult<Void> futureResult = new FutureResult<>();
    if (!handlePrechecks(futureResult, callback)) {
      return futureResult;
    }
    Callback<String> stringCallback = (result, exception) -> {
      // Create a new Callback<Void> and call it, ignoring the String result.
      callback.onCompletion(null, exception);
    };
    Callback<Void> wrappedCallback =
        restRequest != null ? createIdConverterCallbackForTtlUpdate(restRequest, blobId, futureResult, stringCallback)
            : callback;
    Exception exception = null;
    try {
      // to make sure Blob ID is ok
      checkBlobId(blobId);
      if (!deletedBlobs.contains(blobId) && blobs.containsKey(blobId)) {
        InMemoryBlob blob = blobs.get(blobId);
        BlobProperties currentProps = blob.blobProperties;
        long newTtlSecs = Utils.getTtlInSecsFromExpiryMs(expiresAtMs, currentProps.getCreationTimeInMs());
        blob.blobProperties.setTimeToLiveInSeconds(newTtlSecs);
        if (notificationSystem != null) {
          notificationSystem.onBlobTtlUpdated(blobId, serviceId, expiresAtMs, null, null);
        }
      } else if (deletedBlobs.contains(blobId)) {
        exception = new RouterException("Blob has been deleted", RouterErrorCode.BlobDeleted);
      } else {
        exception = new RouterException("Blob not found", RouterErrorCode.BlobDoesNotExist);
      }
    } catch (RouterException e) {
      exception = e;
    } catch (Exception e) {
      exception = new RouterException(e, RouterErrorCode.UnexpectedInternalError);
    } finally {
      completeOperation(futureResult, wrappedCallback, null, exception);
    }
    return futureResult;
  }
Set the lifeVersion of this blob.
@param lifeVersion The lifeVersion to set.
ambry-test-utils/src/main/java/com/github/ambry/router/InMemoryRouter.java