-
Notifications
You must be signed in to change notification settings - Fork 370
Unexpected 412 Response from CloudBlockBlob.DownloadText() #541
Description
Hello! I was hoping you could help clarify a behavior I'm seeing.
I'm using blob storage as a basic cache, and I may have multiple readers and a single writer. The blobs are just JSON representations of objects. Per the default strategy explained in Managing Concurrency in Microsoft Azure Storage:
If you do not explicitly specify a strategy last writes wins is the default.
Also, from Exam Ref (70-532) Developing Microsoft Azure Solution, Chapter 4:
Any updates made to a blob are atomic. While an update is in progress, requests to the blob URL will always return the previously committed version of the blob until the update is complete.
And that's exactly what I want. I realize that the storage library may have some different behavior, and that's what I wanted to clarify.
My basic cache read is doing the following:
public CacheItem RetrieveItem(string container, string key)
{
CloudBlockBlob blockBlob = BlobHelper.GetBlob(container, key);
blockBlob.FetchAttributes();
CacheItem item = new CacheItem();
item.Metadata = blockBlob.Metadata;
item.Key = blockBlob.Name;
item.Value = blockBlob.DownloadText();
return item;
}
My basic cache write is doing this:
public void StoreItem(string container, CacheItem cacheItem)
{
// parameter validation code omitted
CloudBlockBlob blockBlob = BlobHelper.GetBlob(container, cacheItem.Key);
// Add the value
blockBlob.UploadText(cacheItem.Value);
// Add metadata
blockBlob.Metadata.Clear();
foreach (var item in cacheItem.Metadata)
{
blockBlob.Metadata.Add(item);
}
// Commit metadata.
blockBlob.SetMetadata();
}
In production, we've occasionally gotten 412 responses from that .DownloadText() call. The stack trace looks like this:
Message: The remote server returned an error: (412) The condition specified using HTTP conditional header(s) is not met..
Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext):0
Microsoft.WindowsAzure.Storage.Blob.CloudBlob.DownloadToStream(Stream target, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext):29
Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.DownloadText(Encoding encoding, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext):17
XXXXXXXX.RetrieveItem(String container, String key):46
The particular blob that's causing this issue is 12 MB, so it seems entirely possible to me that I could have a write taking place (singleton writer) while there are reads happening.
Is this behavior expected? Is there any way I can get that "last write wins" / "requests return previously committed blob until the update is complete" behavior without getting 412 errors?
Thanks in advance!
Vinnie