Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Inspired by the non-locking implementation proposed in this thread: Locking during cache population , the following code is an attempt to (about) do the same using the azure cache. As I'm totally green on the azure cache I'd appreciate input on best practices or pitfalls... I should add that this method is assumed to be the only interaction with the azure cache in the application.

public class AzureCacheWrapper
{
    private readonly DataCache cache;

    public AzureCacheWrapper(DataCacheFactory cacheFactory)
    {
        this.cache = cacheFactory.GetDefaultCache();
    }

    public T GetOrAdd<T>(string key, Func<T> factoryMethod)
    {
        var factoryMethodAsLazy = new Lazy<T>(factoryMethod);
        var cachedFactory = cache.Get(key) as Lazy<T>;
        if (cachedFactory == null)
        {
            try
            {
                cache.Add(key, factoryMethodAsLazy);
                cachedFactory = factoryMethodAsLazy;
            }
            catch (DataCacheException ex)
            {
                if (ex.ErrorCode != DataCacheErrorCode.KeyAlreadyExists)
                {
                    throw;
                }

                // We know for sure that the key exists at this point:
                // Two concurrent callers tried to get it, and this thread
                // happened to be deadlock victim.
                cachedFactory = (Lazy<T>)cache.Get(key);
            }
        }

        return cachedFactory.Value;
    }
}
share|improve this question

2 Answers 2

up vote 2 down vote accepted

I do not have an Azure account, so I cannot test this, but does this work in general? The linked question uses a MemoryCache which is in-memory and probably references the added objects directly. As Azure cache is a distributed system, that will probably not work and the values need to be serialized in some way to be passed to the remote cache.

As I was writing this, I stumbled upon this SO question which clearly shows that Lazy<T> is serializable and thus can probably be stored in Azure, but the value will be evaluated on serialization. Basically, using Lazy<T> does not give you any advantage here, because of the aforementioned side-effect of putting it in the cache.

            // We know for sure that the key exists at this point:
            // Two concurrent callers tried to get it, and this thread
            // happened to be deadlock victim.

That state is probably not true, because the cache item with that key might have expired between the exception and the call to Get. Granted, that this is relatively unlikely and heavily depends on how small the cache timeout is, but it could happen. This scenario could be avoided if you retried the whole method upon receiving a DataCacheErrorCode.KeyAlreadyExists error code.

share|improve this answer
    
Add() seems (deducted from source) to serialize before checking if key exists, which does indeed render Lazy unneccessary, a recalculation seems inevitable at this point –  Tewr Aug 11 at 15:32
// Two concurrent callers tried to get it, and this thread
// happened to be deadlock victim.

This is inaccurate. The situation that can happen here is a race condition, but not a deadlock (i.e. two processes waiting on each other, which some systems solve by killing one of the processes).

share|improve this answer
1  
Imo these type of answers should be considered as comments –  bruce14 Aug 11 at 16:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.