Creating Append Blob only if it does not exists safely
I’m working on a small side-project where I need some multiple-writers-safe storage for storing logging-like events. For this the Azure’s Append Blob is a good match.
But the blob itself is limited in size and number of blocks. Thus I have to, from time to time, create a new one. And I decided to do it regularly. Every month in my case. Only problem is how to reliably create these blobs… The container has a handy CreateIfNotExistsAsync
method. But AppendBlob
has only CreateOrReplaceAsync
and for my scenario the “replace” part is really not desired. Although I can use the ExistsAsync
method, the race condition alarm triggers immediately.
Luckily there’s a way to do kind of optimistic locking. I can use the CreateOrReplaceAsync
overload with AccessCondition
and use GenerateIfNotExistsCondition
. That way I’ll get an exception, which I can handle, when the blob already exists and it will not be replaced.
var blob = container.GetAppendBlobReference("foobar.txt");
try
{
await blob.CreateOrReplaceAsync(
AccessCondition.GenerateIfNotExistsCondition(),
new BlobRequestOptions() { RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(1), 10) },
null);
}
catch (StorageException ex) when (ex.RequestInformation?.HttpStatusCode == (int)HttpStatusCode.Conflict)
{ }
Here I’m using the mentioned GenerateIfNotExistsCondition
(together with LinearRetry
policy as one should, in case something is not healthy in the cloud at the moment), then catching the StorageException
and checking whether the status was 409 Conflict
. If so I can be 99% sure the blob exists and I can safely continue. Else it was just created. Given that I’m trying it and handling the “already exists” state, not the other way around, I don’t have the race condition anymore.
The GenerateIfNotExistsCondition
is not limited only to this method. You can use it on other places too. Although in this particular case it fits nicely (maybe that’s why it’s also mentioned in the overload’s description – if you’d ever look at that overload).
For me now, to find good format for “streaming” or appending, respectively. I think CSV will do.