9

I have a situation in which I currently upload a CloudBlockBlob using :

CloudBlockBlob.UploadFromStreamAsync

and then immediately afterward I set a bunch of user metadata on it.

The issue is: I have an Event Grid event which is triggered when the blob is uploaded, but the event handler requires the metadata. Long story short, it's a race condition wherein I have to "hope" that the metadata has been set before my event handler responds to the block blob upload.

Is there some way to both upload the block blob (file) and set its metadata in a single operation?

Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
vargonian
  • 3,064
  • 3
  • 27
  • 36
  • Could you await? – Lyco Aug 16 '18 at 18:39
  • I'm not sure if you're referring to the async/await pattern, but in any case, I don't see how that would get around needing to upload the image, and then set the metadata as two discrete steps. The race condition happens between these two steps. – vargonian Aug 16 '18 at 20:07
  • When you update metadata, Event Grid event will be fired again AFAIK. – Sean Feldman Aug 16 '18 at 20:30
  • @SeanFeldman Unfortunately that doesn't seem to be the case, though that would certainly be helpful! – vargonian Aug 16 '18 at 21:14
  • Content updates raise events, but not metadata? Sounds like a bug. – Sean Feldman Aug 17 '18 at 01:15
  • 4
    Yes, you can. Simply set the metadata by using CloudBlockBlob.Metadata.Add before uploading the blob. – Gaurav Mantri Aug 17 '18 at 03:02
  • "Dirty workaround": the event handler will return an error (500) for not exist metadata. That's happen first time. The next time (after 10/30 seconds), the event handler will get the blob metadata and the return code = OK. – Roman Kiss Aug 17 '18 at 05:15
  • 1
    Gaurav is correct. Just set the metadata on the blob before calling Upload. – juunas Aug 17 '18 at 06:57
  • @GauravMantri Thank you so much. I was mistakenly led to believe that I needed to call "FetchAttributes/Async" on a block blob before I would be allowed to change its metadata, which clearly fails for a non-existent blob, so I thought it had to be done in 2 steps. This completely solves my problem. – vargonian Aug 17 '18 at 16:51

1 Answers1

7

As juunas said, you could just set the metadata on the blob before calling Upload. I make a little demo with .Net Console you could refer to.

public static void Main(string[] args)
{
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
    CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
    CloudBlobContainer container = cloudBlobClient.GetContainerReference("container");
    CloudBlockBlob cloudBlockBlob = container.GetBlockBlobReference("hello.txt");
    MemoryStream msWrite = new MemoryStream(Encoding.UTF8.GetBytes("aaaaaa"));
    msWrite.Position = 0;
    cloudBlockBlob.Metadata["category"] = "guidance";
    using (msWrite)
    {
        cloudBlockBlob.UploadFromStream(msWrite);
    }
 }

The output in blob on portal: enter image description here

Gandhi
  • 11,875
  • 4
  • 39
  • 63
Joey Cai
  • 18,968
  • 1
  • 20
  • 30
  • your demo shows two storage operations such as a SetMetadata and UploadFromStream. For single operation is enough to populate (initialize) a Metadata dictionary using CloudBlockBlob.Metadata.Add method like is commented by @GauravMantri. – Roman Kiss Aug 17 '18 at 11:14
  • @juunas Thank you again. As I mentioned above, I was mistakenly led to believe that I needed to call "FetchAttributes/Async" on a block blob before I would be allowed to change its metadata, which clearly fails for a non-existent blob, so I thought it had to be done in 2 steps. – vargonian Aug 17 '18 at 16:52
  • 1
    You should remove `cloudBlockBlob.SetMetadata();` as this will cause the code to fail if the file does not yet exist. I have edited the code. – Alex AIT Dec 10 '19 at 08:07
  • Does setting metadata will work in the same way for `OpenWriteAsync` and `CommitAsync`? – Gautam Kumar Samal May 17 '21 at 06:45