Got more questions? Find advice on: SQL | XML | Regular Expressions | Windows
in Search
Welcome to AspAdvice Sign in | Join | Help

Cache Removed Callback Timing

Last post 10-03-2005, 3:09 PM by sunisha. 8 replies.
Sort Posts: Previous Next
  •  09-30-2005, 2:46 PM 12964

    Cache Removed Callback Timing

    I asked the following in the microsoft.public.dotnet.framework.aspnet.caching newsgroup but have not heard a response. i saw your article on caching and thought that you might have an answer...

    I am trying to implement a callback when a cache item expires (or is

    removed). Below is sample code from my page that does just that...

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As

    System.EventArgs) Handles MyBase.Load

    If (Not Page.IsPostBack) Then

    Dim eventLogEntry As New EventLog("Application", ".",

    "Caching")

    eventLogEntry.WriteEntry("MyCachedItem put in cache.",

    EventLogEntryType.Information)

    Cache.Add("MyCachedItem", TextBox1.Text, Nothing, _

    Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(20), _

    CacheItemPriority.Low, New

    CacheItemRemovedCallback(AddressOf CacheRemoved))

    End If

    End Sub

    Private Sub CacheRemoved(ByVal key As String, ByVal value As Object,

    ByVal reason As CacheItemRemovedReason)

    Dim eventLogEntry As New EventLog("Application", ".", "Caching")

    eventLogEntry.WriteEntry(key + " expired in cache.",

    EventLogEntryType.Information)

    End Sub

    I am setting the cache timeout to 20 seconds...but when I look at the event

    log, I don't see the expiration eventlog item in 20 second. I see different

    timespans (not the 20 seconds that I am expecting) when the callback is

    actually called...

    Date: 9/29/2005 Time: 4:33:40 PM MyCachedItem put in cache.

    Date: 9/29/2005 Time: 4:35:00 PM MyCachedItem expired in cache.

    Date: 9/29/2005 Time: 4:42:09 PM MyCachedItem put in cache.

    Date: 9/29/2005 Time: 4:43:00 PM MyCachedItem expired in cache.

    Date: 9/29/2005 Time: 4:44:35 PM MyCachedItem put in cache.

    Date: 9/29/2005 Time: 4:46:00 PM MyCachedItem expired in cache.

    Am I doing something wrong? Or is this something to do with the GC (is that

    how cache items are expired)? Thanks for any help!!


    Steven A Smith
    President, AspAlliance LLC
    CIO, Lake Quincy Media, LLC
  •  09-30-2005, 2:49 PM 12965 in reply to 12964

    Re: Cache Removed Callback Timing

    The behavior you're seeing is due to the way absolute cache expirations are implemented.  They are not implemented with a timer that starts when the item is created and fires off when the time runs out.  Rather, the item in the cache has an expiration property associated with it.  Whenever a new request for that cached item comes in, the expiration property is inspected and if it has expired, then the cached item is deleted.  So it is very possible that you could cache something at 1:00:00 for 5 seconds, not access it again until 1:00:39 and only at that time is it removed (and the CacheItemRemovedCallback invoked).  The other point at which the item may be removed is whenever the cache runs into memory pressure and scavenges memory by deleting expired or infrequently used items.

    Short answer - you cannot count on *when* the CacheItemRemovedCallback will be called for time-based cache dependencies.  If you need that, you'll need to use your own Timer.


    Steven A Smith
    President, AspAlliance LLC
    CIO, Lake Quincy Media, LLC
  •  09-30-2005, 3:19 PM 12966 in reply to 12965

    Re: Cache Removed Callback Timing

    Thank you very much for the reply!  So I don't understand what the point of the callback is if you write code which checks if the item is in cache and if not "re-create" it and put it in the cache...

    Dim cacheInnerList As ArrayList = CType(Utility.GetFromCache(cacheName), ArrayList)

    If cacheInnerList Is Nothing Then
     Me.PopulateInnerList(Criteria)

     Dim onCacheRemove As CacheItemRemovedCallback
     onCacheRemove = New CacheItemRemovedCallback(AddressOf CacheRemoveCallback)

     Utility.SetToCache(cacheName, InnerList, Criteria, onCacheRemove)
    Else
    ...
    End If

    I used the example code in Jonathan Goodyear's article (http://angrycoder.com/article.aspx?cid=5&y=2001&m=8&d=7) and added some time information to the cache item written by the callback method and it doesn't seem that the callback is called when I visit the page (it is called some arbitrary time -- not the aboslute expiration time).  I guess using sliding expiration would be the same thing except the cache item wouldn't expire if it kept getting accessed?  Thanks for your help!

    Sunish

  •  09-30-2005, 5:00 PM 12967 in reply to 12966

    Re: Cache Removed Callback Timing

    You are correct, there's little point in using a callback to attempt to refresh the data in the cache.  Jonathan's article is from back in 2001, when he and many others (including myself) were very excited about the potential of callbacks.  Unfortunately, the reality of the situation is that callbacks are fairly useless unless you want to use them to log cache behavior (in order to tweak your caching strategy).  There's no real-time scenario I've found where the callback is a useful feature.

    What *would* be useful, but which won't be in ASP.NET 2.0 despite my request for it, is another callback that fires off *before* the item is removed from the cache.  A CacheItemRemovingCallback or CacheItemAboutToBeRemovedButNotQuiteYetCallback would allow for scenarios like the one JG describes in that article, wherein you can update an item in the cache as it gets old, but before it is actually removed from the cache.

    Today if you try to use callbacks to refresh cache items, most of the time you only succeed in adding more load to your database.  The reason for this is that the item is not typically expired (and the callback called) until something comes looking for it.  When that happens, the calling method gets null returned from the Cache object at the same time (more or less) that the callback is invoked.  At this point, the calling method is going to revert to its cache-expired behavior and go re-fetch the data, while at the same time your callback is doing the same thing.

    I'm working on a cache implementation/extension that will allow for automatically renewing cache entries, wherein the item's value is renewed on a background thread such that no user has to wait for the renewal, but yet the cached data is guaranteed to never be more than TimeSpan old.  Look for more on this in my blog soon.


    Steven A Smith
    President, AspAlliance LLC
    CIO, Lake Quincy Media, LLC
  •  09-30-2005, 10:42 PM 12972 in reply to 12967

    Re: Cache Removed Callback Timing

    Hey Steven,

    Thank you very much for the explanation!  I get what you are saying about the cache item not being removed...but I am using JG code in his article and I see that the cache removed callback is called without the "user-intervention".  What I mean is I go to the page and add a cache item which has an absolute expiration of 10 seconds...I wait a minute and get the cache item CacheStatus which is created in the cache removed callback and I see that the CacheStatus has a date/time which is not a minute later but earlier but not 10 seconds as I would have expected.  Below is the page I am "testing"...

    cacheexpirationcallback.aspx

    <%@ Page Language="C#" %>

    <script language="C#" runat="server">
      private void Page_Init(object sender, EventArgs e)
      {
        //assign button event handlers
        this.addCacheItem.Click += new EventHandler(
          addCacheItem_Click);
        this.checkStatus.Click += new EventHandler(
          checkStatus_Click);
      }

      private void MyCacheItemRemovedCallback(string key,
        object val, CacheItemRemovedReason reason)
      {
        //set cache status, so that we can view what
        //happened the next time we request a status update
        Cache.Insert("CacheStatus","KEY: " + key + "<br />VALUE: "
          + val + "<br />REASON: " + reason.ToString()
          + "<br />TIME: " + DateTime.Now.ToString());
      }

      private void addCacheItem_Click(object sender, EventArgs e)
      {
        //create an instance of the callback delegate
        CacheItemRemovedCallback callBack =
          new CacheItemRemovedCallback(MyCacheItemRemovedCallback);
      
        //insert the item in cache that expires in 10 seconds.
        //assign the callback instance to it
        Cache.Insert(keyBox.Text,valueBox.Text,null,
        DateTime.Now.AddSeconds(10), Cache.NoSlidingExpiration,
        CacheItemPriority.Default, callBack);

        //clear status label
        statusLabel.Text = "Added " + keyBox.Text + "<br />TIME: " + DateTime.Now.ToString();
      }

      private void checkStatus_Click(object sender, EventArgs e)
      {
        //if there is a status to report, display it and
        //remove it from cache.
        if(Cache["CacheStatus"] != null)
        {
          statusLabel.Text = Cache["CacheStatus"].ToString();
          //Cache.Remove("CacheStatus");
        }
      }
    </script>

    <html>
    <head>
    <title>CacheItemRemovedCallback Demo</title>
    </head>
    <body>
    <form runat="server">
      Key: <asp:TextBox id="keyBox" runat="server" />
      <br />
      Value: <asp:TextBox id="valueBox" runat="server" />
      <br />
      <asp:Button id="addCacheItem" Text="Add Item"
        runat="server" />
        <asp:Button id="checkStatus" Text="Check Status"
        runat="server" />
      <br /><br />
      <b><asp:Label id="statusLabel" runat="server" /></b>
    </form>
    </body>
    </html>

    Sunish

  •  10-03-2005, 12:32 PM 12991 in reply to 12972

    Re: Cache Removed Callback Timing

    Could be the cache engine is scavenging the memory in the meantime.  I'm not suggesting that it will *only* be expired the next time it is accessed after its absolute expiration -- it's still possible the cache object will decide to expire it at some point.  It's just not something you can count on to happen at any particular time.
    Steven A Smith
    President, AspAlliance LLC
    CIO, Lake Quincy Media, LLC
  •  10-03-2005, 1:24 PM 12996 in reply to 12991

    Re: Cache Removed Callback Timing

    So is the cache removed callback something that I should stay away from?  I was hoping to get some direction based on past experience from the forum members.  I mean I don't see it as a big deal to "refresh" the cache when an user attempts to access a cacheitem which is expired based on the absolute expiration and have that one user take the "hit" in the time it takes refreshing the data. 

    Another question I have is "threading" issues for accessing/writing cache items...whats happens if I have two requests for the same cache item and it is expired and then both users attempt to insert the cache item back into the cache?  Should I use Insert method rather than the Add method so that I don't get an exception if the cache item already exists?  Is the cache.insert method thread safe?

    Thanks again!

    Sunish

  •  10-03-2005, 1:35 PM 13000 in reply to 12996

    Re: Cache Removed Callback Timing

    Yes, unless you simply want to use it to collect some data on how your cached items are expiring, the callback is not terribly useful in most scenarios.  As for the threading issues, I've never encountered any but I always use Insert.  You should also take a look at my cache access pattern, which shows the proper way to check if the item is expired and then repopulate it.  Failing to do this properly *can* cause occasional exceptions.


    Steven A Smith
    President, AspAlliance LLC
    CIO, Lake Quincy Media, LLC
  •  10-03-2005, 3:09 PM 13007 in reply to 13000

    Re: Cache Removed Callback Timing

    Yes I read your excellent blog on that topic before proceeding with what I am implementing.  Thank you very much for your help/insight on this topic!

    Sunish Abraham

     

View as RSS news feed in XML