Skip to content
This repository was archived by the owner on Aug 1, 2024. It is now read-only.
This repository was archived by the owner on Aug 1, 2024. It is now read-only.

Unexpected 412 Response from CloudBlockBlob.DownloadText() #541

@vinniep79

Description

@vinniep79

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions