protected Response<Void> updateBlobMetadata(AzureBlobLayoutStrategy.BlobLayout blobLayout,
      BlobProperties blobProperties) {
    Map<String, String> metadata = blobProperties.getMetadata();
    BlobClient blobClient = createOrGetBlobStore(blobLayout.containerName).getBlobClient(blobLayout.blobFilePath);
    /**
     * When replicating, we might receive a TTL-UPDATE for a blob from replica-A and a DELETE for the same blob from replica-B.
     * The thread-local cache functions as a write-through cache. We write the TTL-UPDATE from replica-A through this cache,
     * followed by the DELETE from replica-B. The ETag changes in the cloud after each update, and we avoid additional read
     * requests from the cloud between updates. This means we are not performing read-modify-write
     * operations on the blob metadata in the cloud, so we cannot rely on ETag matching to constrain updates.
     * Additionally, ETag matching is primarily useful for concurrent updates, which is not relevant here because all
     * replicas for a partition are scanned serially by the same thread. This is a departure from the previous design,
     * where all replicas for a partition were scanned concurrently, often resulting in races during cloud updates.
     */
    BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setIfMatch("*");
    Response<Void> response = blobClient.setMetadataWithResponse(metadata, blobRequestConditions,
        Duration.ofMillis(cloudConfig.cloudRequestTimeout), Context.NONE);
    return response;
  }
Synchronously update blob metadata
@param blobLayout Blob layout
@return HTTP response and blob metadata
ambry-cloud/src/main/java/com/github/ambry/cloud/azure/AzureCloudDestinationSync.java