possible bug in Refresh() (or at least some inconsistent behavior)

Dec 17, 2011 at 6:16 PM

When someone calls Refresh(), the assumption is that they want live data, correct? When you write the code, the object that is returned immediately is usually the cached version and you can specify a callback to handle the updated data, which works fine most of the time.

But if you call Refresh() when there is not yet any data in the in-memory cache but there is data in the isostore cache, the return value is a newly-created instance, and the callback gets passed the *cached* value. (assuming you are using the CacheThenRefresh directive).

In other words, in the normal case:

return value = cached item
callback = updated item

but in the 'fresh' case:

return value = new item
callback = cached item

And thus no 'refreshed' data is even loaded. It is simple to reproduce this issue. Simply put a call to DataManager.Current.Refresh() at the beginning of your app, before a call to Load().

I know the documentation says that the callback lets you know when the 'operation' completes, and technically the operation is loading from the cache the first time, but that is not the expected behavior when a dev calls Refresh(). When Refresh is called, the callback should only be triggered when new live data has been loaded.

Am I missing something?

 

Coordinator
Dec 22, 2011 at 10:26 AM

Hi Brian -

But the callback gets called *again* when the live data finally loads, right?

So to be clear you get the following.  Sorry, I'm overseas so I can't try it myself!

Fresh case, no cache:

return value: new (default) item

callback: live load result

Fresh case with cache:

return: new (default item)

callback: cached value

callback: live value

If that's the case, what your asking for is to suppress the cached callback in the Refresh case?  I think I can do that - what's happening here is that Refresh is just a shorthand for Invalidate + Load.  So the Invalidate clears out some other state which I believe is what causes that initial cache load to come through.  It'll basically take a bit of a hack to plumb through a bit to stop the CacheItem from notifying on the cache load, but it's not too bad. 

I'm not in a position to do any real work on this until I get back home after the New Year - but I'll get to it then along with some other fixes.

Thanks,

Shawn

 

Dec 22, 2011 at 7:21 PM

Nope, the callback only gets fired once (with the cached data). I debugged it and I think I found the cause. In Invalidate(), it sets the CacheEntry's expiration date to Now (so it is expired), but then later when LoadInternal checks the CacheValueLoader's IsValid property, *its* expiration date is still in the future (assuming the cache has not expired yet based on its configuration). At that point, it calls StartLoading with force=false and passing in the CacheValueLoader, which results in the callback being fired with the cached data.

I tried changing the SetForRefresh() method to always call _cacheLoader.SetExpired(), but that doesnt actually update the CacheValueLoader's expiration time (instead, it sets the state to Error, and doing so resulted in some strange behavior). I then modified the CacheValueLoader.SetExpired() method to set its expiration date to Now, and that seems to work OK, though I also had to comment out the part about setting the state to Error, so I am not sure of what downstream effects it is having.

Since I am using this in a background agent and need to wait for the Refresh() to complete, my other work-around is to call LoadFromCache() first (which is synchronous) and then call Refresh. That works but unnecessarily slows things down since I dont want/use the cached value read from disk.

Anyway, I figure with the holidays that this would be something that wouldnt be fixed right away and it is not blocking me since I have a few work-arounds, but I thought I would report it so you could take a look.

Thanks,

 - brian

Coordinator
Jan 4, 2012 at 9:35 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Jan 4, 2012 at 9:36 PM

Hi Brian -

I created a work item for this and attached a potential fix, can you please test?

http://agfx.codeplex.com/workitem/17196

Thanks

Jan 4, 2012 at 10:10 PM

I see the work item, but it doesnt show any attached files. Maybe I am missing something?

Coordinator
Jan 5, 2012 at 2:18 PM

Bah, it didnt' stick, please try again.

Jan 5, 2012 at 8:24 PM

I tried the fix, but it didnt help. The root cause still exists: the call to _cacheLoader.IsValid (from LoadInternal()) still returns 'true' causing cached data to be returned. I attached a modified MainPage.xaml.cs that you can use in your Weather sample to replicate the bug.