Thursday, June 02, 2005 9:52 PM Olaf Conijn

Enterprise Library caching logic... design flaw?

A colleague of mine (somehow known as Obiwan Jacobi) pointed out what I think is a design mistake in EntLibs CacheManager API.

The flaw lies in the publicly exposed CacheManager.Contains(string) method.

Exposing this member almost ‘instructs’ a consumer of the CacheManager to write code similar to:

if (!CacheManager.Contains(cacheKey))

{

      //fill cache

}

object cachedObject = CacheManager.GetData(cacheKey);

You’ve probably already noted the potential bug in the logic above, what if……. there’s a scavenger run in between the first and last line of code.

 

Hardly seems like a good pattern or practice, does it? ;)

# re: Enterprise Library caching logic... design flaw?

Friday, June 03, 2005 10:26 AM by Olaf Conijn

Why is this a design error? When you put something in the cache then you already have a reference to it right? Ofcourse it could be the case that the item is removed by te scavenger between the .Contains(..) and the .GetData(..). But that's a very minor change... This can easily be tested when cached objects can never be null.

object cacheObject

do{
if(!CacheManager.Contains(cacheKey)) {
cacheObject = CreateVeryExpensiveObjectX();
}else{
cachedObject = CacheManager.GetData(cacheKey);
}
}while(cachedObject!=null);

# re: Enterprise Library caching logic... design flaw?

Friday, June 03, 2005 11:44 AM by Olaf Conijn

Your solution should work, true.

Though the API could have been more intuitive on this point. Bugs that have a very minor change to occur are hard to trace, did you know? ;)


Looping through code seems like a bit confusing, when reading the code out of the context.

IMHO the right way to pul items from a Cache should look something like this:

Apple o = CacheManager.GetData(cacheKey) as Apple;
if (o == null)
{
CacheManager.SetData(cacheKey, o = GoFetchAnApple());
}

Nice and compact, isnt it?

Worst thing that could happen know is adding the item multiple times to the cache, because we did not write syncronisation code (could be just a single lock around the code snippet). But we'll never end up without an apple at the end of this code.

# re: Enterprise Library caching logic... design flaw?

Tuesday, June 07, 2005 11:46 PM by Olaf Conijn

Hi Olaf -

I agree that your code snippet is problematic, but I disagree with the conclusion that there is a design flaw. The Contains method is there to support a different (and admittedly minor) scenario where you want to check if an item is in the cache but don't want to actually pull it out. You may want to do this to determine whether an item should be proactively retrieved from the master data source.

There is always a risk that people will use some features incorrectly - we try to mitigate this by showing the correct techniques in the code samples and QuickStarts.

Tom

# re: Enterprise Library caching logic... design flaw?

Tuesday, August 16, 2005 8:27 PM by Phillip Jacobs

I don’t think the problem is with the code. It does its job exactly as it was designed to do. You are right in believing a problem could arise from misuse or misunderstanding.

It won't happen very often but it can happen and Steve Smith wrote an article calling the method you propose a Caching Pattern. It is the right way to code when accessing the cache.
http://weblogs.asp.net/ssmith/archive/2003/06/20/9062.aspx

You can also find more evidence of this problem by way of Scott Cate. He pulled much of his hair out trying to figure out why he got an error 1 out of a 100 times the page was accessed. He lists a couple of static methods he developed to help keep this from happening. Check it out! ;)
http://scottcate.mykb.com/Article_5CB26.aspx.