Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cache expires before it supposed to

Can someone help me here? I have following code to store and revieve catch, however, it doesn't work. The cache expires in mins even I set it to 14 days in slidingExpiration. Thanks in advance!

public static List<ReplyDTO> VideoCommentList()
{
     List<ReplyDTO> replyList = new List<ReplyDTO>();
     if (HttpRuntime.Cache["videoComment"] == null)
     {
         HttpRuntime.Cache.Remove("videoComment");
         HttpRuntime.Cache.Insert("videoComment", replyList, null, Cache.NoAbsoluteExpiration, TimeSpan.FromDays(14));
     }
     else
     {
         replyList = (List<ReplyDTO>)HttpRuntime.Cache["videoComment"];
     }

     if (replyList.Count > 8)
     {
         replyList = replyList.OrderByDescending(x => x.DateCreated).Take(8).ToList();
     }
     else
     {
         replyList = replyList.OrderByDescending(x => x.DateCreated).ToList();
     }
     return replyList;
}

public static List<ReplyDTO> AddVideoComment(ReplyDTO replyDTO)
{
     List<ReplyDTO> replyList = new List<ReplyDTO>();
     replyList = VideoCommentList();
     replyList.Add(replyDTO);
     HttpRuntime.Cache.Insert("videoComment", replyList, null, Cache.NoAbsoluteExpiration, TimeSpan.FromDays(14));

     if (replyList.Count > 8)
     {
          replyList = replyList.OrderByDescending(x => x.DateCreated).Take(8).ToList();
     }
     else
     {
          replyList = replyList.OrderByDescending(x => x.DateCreated).ToList();
     }
     return replyList;
}
like image 896
Jack Avatar asked Jan 17 '23 17:01

Jack


2 Answers

ASP.net cache is in-memory, so if your IIS process or application pool recycles it will get clear. You can check following things which can cause recycling of process

  • If you modify web.config, IIS shutdown the old instance and slowly transfer the traffic to a new instance, in this process in-memory is recycled. How to check this: You can detect this situation by checking the AppDomain.IsFinalizingForUnload and logging that during the callback.
  • Application Pool Recycling: There is a configuration in IIS, according to which if IIS process is idle for a specified time, it recycles it. You can check this on server, and increase this time or disable the recycling altogether.
  • Every process has limitation on how much memory it can consume, if you are adding too many objects in memory, it will increase the memory consumption of IIS, and in critical time OS will recycle the process.

EDIT

In your program you are adding replyList item to cache and then doing .Take() operation. As replyList is reference object, if you modify it, it will get updated in the cache also. So if in your program, if you do replyList == null it will update the item in cache.

So modify your code like this and try

public static List<ReplyDTO> VideoCommentList()
{
    List<ReplyDTO> replyList = new List<ReplyDTO>();
    if (HttpRuntime.Cache["videoComment"] == null)
    {
        //Call to .Remove is not required
        //HttpRuntime.Cache.Remove("videoComment");
        HttpRuntime.Cache.Insert("videoComment", replyList, null,
                         Cache.NoAbsoluteExpiration, TimeSpan.FromDays(14));
    }
    else
    {
        //No need to check count > 8, Take will handle it for you
        replyList = ((List<ReplyDTO>)HttpRuntime.Cache["videoComment"])
                        .OrderByDescending(x => x.DateCreated)
                        .Take(8).ToList();
    }
    return replyList;
}

public static List<ReplyDTO> AddVideoComment(ReplyDTO replyDTO)
{
    //Read from cache
    List<ReplyDTO> replyList = ((List<ReplyDTO>)HttpRuntime.Cache["videoComment"]);
    if(replyList == null)
        replyList = VideoCommentList();
    replyList.Add(replyDTO);
    HttpRuntime.Cache.Insert("videoComment", replyList, null, Cache.NoAbsoluteExpiration, TimeSpan.FromDays(14));

    //Here you are creating a new list, and not referencing the one in the cache
    return replyList.OrderByDescending(x => x.DateCreated).Take(8).ToList();
}

IMPORTANT SUGGESTION

If you want to check when and why your object is removed from the cache, you can take help of CacheItemRemovedCallback option on the insertion. Using this and CacheItemRemovedReason argument, you can log the reason of object removal from cache. Reasons

  1. Removed - Your code has removed the item from cache by calling Insert or Remove method.
  2. Expired - The item is removed from the cache because it expired.
  3. Underused - When system run low on memory, it freed up memory by removing item from the cache.
  4. DependencyChanged - The item is removed from the cache because the cache dependency associated with it changed. (In your case it is not valid)

Hope this information helps you.

like image 157
Amar Palsapure Avatar answered Jan 30 '23 13:01

Amar Palsapure


In order to track down WHY your item is being removed from cache, I'd recommend using a different overload of the HttpRuntime.Cache.Insert method that allows you to specify a CacheItemRemovedCallback callback function.

Cache.Insert Method (String, Object, CacheDependency, DateTime, TimeSpan, CacheItemPriority, CacheItemRemovedCallback)

Aside from that your caching code seems good. But once you change your code to specify a callback, log the ejection reason and that will probably give you a better understanding of why your cached item is getting clear.

Like most of the other answers, I suspect that your app is getting recycled/reset for any number of reasons. I think that most apps on a production machine recycle at least once a day, especially in a shared hosting environment. So I'd guess that your data will stay cached for a day at most.

like image 43
slolife Avatar answered Jan 30 '23 13:01

slolife