Caching expiration

Topics: Caching Application Block
Jan 10, 2012 at 11:06 AM

I wanted to set the exipiration policy in order to expire the cached data after every minute.

Here is the code for the same -

Defined the extended format first as -

ExtendedFormatTime

objExtendedFormat = new ExtendedFormatTime("* * * * *");

 

After that have added the data to cache -

objCacheManager.Add(

 

"Key", "TestData1", CacheItemPriority.Normal, null, objExtendedFormat);

 

 However, the data doesn't expire after a minute.

What might be going wrong?

 

Jan 11, 2012 at 4:13 AM

If you use the format string "* * * * *" with ExtendedFormatTime that means that the cache item expires every minute.  Note that this is not the same as expiring after one minute.

So if you add an item to the cache at 09:09:59 then the item will be expired 1 second later at 09:10:00.  Based on my tests it seems to be behaving correctly.

Did you use the Contains() method to determine if the item was not expired?  The contains method will not run the expiry logic; you need to attempt to retrieve the item to run the expiry logic or have the scavenger run in the background.

Can you post a small code sample to reproduce what you are seeing?

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jan 11, 2012 at 5:58 AM
randylevy wrote:

If you use the format string "* * * * *" with ExtendedFormatTime that means that the cache item expires every minute.  Note that this is not the same as expiring after one minute.

So if you add an item to the cache at 09:09:59 then the item will be expired 1 second later at 09:10:00.  Based on my tests it seems to be behaving correctly.

Did you use the Contains() method to determine if the item was not expired?  The contains method will not run the expiry logic; you need to attempt to retrieve the item to run the expiry logic or have the scavenger run in the background.

Can you post a small code sample to reproduce what you are seeing?

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 


Hi,

Here's the code snippet. Apologies if its unreadable.

Actually what I want to achieve is expiry after every 24 hours. Initially I tried using Absolute time however, it didn't help. Thus was trying to atleast see if it expires at some interval and tried with every minute.

using

System;

using

System.Collections.Generic;

using

System.Linq;

using

System.Web;

using

System.Web.UI;

using

System.Web.UI.WebControls;

using

Microsoft.Practices.EnterpriseLibrary.Caching;

using

Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;

namespace

Test_EnterpriseLib

{

 

public partial class _Default : System.Web.UI.Page

{

 

/// Minute - 0-59 <br/>

 

/// Hour - 0-23 <br/>

 

/// Day of month - 1-31 <br/>

 

/// Month - 1-12 <br/>

 

/// Day of week - 0-6 (Sunday is 0) <br/>

 

/// Wildcards - * means run every <br/>

 

/// Examples: <br/>

 

/// * * * * * - expires every minute<br/>

 

/// 5 * * * * - expire 5th minute of every hour <br/>

 

/// * 21 * * * - expire every minute of the 21st hour of every day <br/>

 

/// 31 15 * * * - expire 3:31 PM every day <br/>

 

/// 7 4 * * 6 - expire Saturday 4:07 AM <br/>

 

/// 15 21 4 7 * - expire 9:15 PM on 4 July <br/>

 

/// Therefore 6 6 6 6 1 means:

 

/// • have we crossed/entered the 6th minute AND

 

/// • have we crossed/entered the 6th hour AND

 

/// • have we crossed/entered the 6th day AND

 

/// • have we crossed/entered the 6th month AND

 

/// • have we crossed/entered A MONDAY?

 

ICacheManager objCacheManager = CacheFactory.GetCacheManager();

 

 

ExtendedFormatTime objExtendedFormat = new ExtendedFormatTime("* * * * *");

 

protected void Page_Load(object sender, EventArgs e)

{

 

if (!IsPostBack)

{

 

 

// Label3.Text = System.DateTime.Now.ToString();

 

// //if (IsPostBack!=true)

 

// //{

 

// //TimeSpan timespan = new TimeSpan(DateTime.Now.Day,15,18,00);

 

// #region MyRegion

 

 

// //DateTime cacheExpireationTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 21,03,00);

 

// // //AbsoluteTime absoulteExpirationTime = new AbsoluteTime(timespan); //

 

// // AbsoluteTime absoulteExpirationTime = new AbsoluteTime(cacheExpireationTime);

 

// //bool Expired = absoulteExpirationTime.HasExpired();

 

// // Label4.Text =absoulteExpirationTime.AbsoluteExpirationTime.ToLocalTime().ToString(); //absoulteExpirationTime.AbsoluteExpirationTime.ToString();//absoulteExpirationTime.AbsoluteExpirationTime.ToLocalTime().ToString();

 

// // objCacheManager.Add("Key", "TestData1", CacheItemPriority.Normal, null, absoulteExpirationTime);

 

// #endregion

 

// bool expiry = objExtendedFormat.HasExpired();

 

// if (expiry == false)

 

// {

 

// objCacheManager.Add("Key", "TestData1", CacheItemPriority.Normal, null, objExtendedFormat);

 

// }

 

// else if (expiry == true)

 

// {

 

// objCacheManager.Remove("key");

 

// Label1.Text = "Expired";

 

// return;

 

// //objCacheManager.Add("Key", "CacheExpired", CacheItemPriority.Normal, null, objExtendedFormat);

 

// }

 

// Label1.Text = Convert.ToString(objCacheManager.GetData("Key"));

 

//}

}

}

 

protected void Button1_Click(object sender, EventArgs e)

{

 

Label3.Text = System.

DateTime.Now.ToString();

 

#region

MyRegion

 

 

//DateTime cacheExpireationTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 21,03,00);

 

// //AbsoluteTime absoulteExpirationTime = new AbsoluteTime(timespan); //

 

// AbsoluteTime absoulteExpirationTime = new AbsoluteTime(cacheExpireationTime);

 

//bool Expired = absoulteExpirationTime.HasExpired();

 

// Label4.Text =absoulteExpirationTime.AbsoluteExpirationTime.ToLocalTime().ToString(); //absoulteExpirationTime.AbsoluteExpirationTime.ToString();//absoulteExpirationTime.AbsoluteExpirationTime.ToLocalTime().ToString();

 

// objCacheManager.Add("Key", "TestData1", CacheItemPriority.Normal, null, absoulteExpirationTime);

#endregion

 

bool expiry = objExtendedFormat.HasExpired();

 

//bool expired =! objCacheManager.Contains("Key");

 

if (expiry == false)

{

objCacheManager.Add(

"Key", "TestData1", CacheItemPriority.Normal, null, objExtendedFormat);

}

 

else if (expiry == true)

{

objCacheManager.Remove(

"key");

Label1.Text =

"Expired";

 

return;

 

//objCacheManager.Add("Key", "CacheExpired", CacheItemPriority.Normal, null, objExtendedFormat);

}

Label1.Text =

Convert.ToString(objCacheManager.GetData("Key"));

 

 

if (objExtendedFormat.HasExpired())

Label1.Text =

"Expired";

 

//Label1.Text = Convert.ToString(objCacheManager.GetData("Key"));

}

}

 

 

 

}

Please advise what neeeds to done in order to achieve expiry at 00:00 hrs everyday.

Jan 11, 2012 at 6:55 AM
Edited Jan 11, 2012 at 6:56 AM

I don't think you should be checking objExtendedFormat.HasExpired().  Firstly the page is creating a new instance of ExtendedFormatTime every time it posts back.  When the ExtendedFormatTime object is created it stores the DateTime it was created and uses that for expiration calculations so when creating a new instance on postback it will result in invalid expirations.  Secondly, you shouldn't use the ExtendedFormatTime to check the cache -- the cache will manage that for you.  

The only time to create an ExtendedFormatTime is when adding an item to the cache.  And once added there is no need to use the ExtendedFormatTime class any longer.

Also, there is no need to remove items from the cache when they are expired -- the cache will manage this for you.  E.g. if you call GetData and the item is expired the item will be removed from the cache (if it was not already scavenged by the background thread) and null will be returned.

If you want your cache to expire every day at Midnight then you should be able to do that using a variation of:

            var cacheManager = EnterpriseLibraryContainer.Current.GetInstance<CacheManager>("Cache Manager");
            
            DateTime localMidnight = DateTime.Today;
            DateTime baseMidnightUTC = localMidnight.ToUniversalTime();
            TimeSpan offset = baseMidnightUTC - localMidnight;
            
            if (offset.Hours < 0)
            {
                offset = offset.Add(TimeSpan.FromHours(24));
            }

            cacheManager.Add("Hello", "World", 
                CacheItemPriority.Normal, 
                null, 
                new ExtendedFormatTime("0 " + offset.Hours + " * * *"));

            object result = cacheManager.GetData("Hello"));
 

The DateTime manipulation is required because internally UTC time is used but (I'm assuming) you want to expire at midnight local time.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jan 11, 2012 at 9:24 AM

Hi,

Many thanks for your reply.

I am currently using EntLib 4.1 and supposed to use only this. So when I create an instance of cachemanager, I use the following.

var cacheManager = CacheFactory.GetCacheManager();

Is there any difference between

var cacheManager = EnterpriseLibraryContainer.Current.GetInstance<CacheManager>("Cache Manager");

and the above ?

Also, just to check whether the cache expires and returns null, I tried with AbsoluteTime (considering UTC conversions)  however, the cache wasn't cleared. Here's the Code on Page Load. My system time zone is GMT+5:30

var cacheManager = CacheFactory.GetCacheManager();



            Label1.Text = Convert.ToString(cacheManager.GetData("Hello"));
            
            //DateTime localMidnight = DateTime.Today;
            DateTime expiryTime = new DateTime(2012, 01, 11, 21, 55, 0).ToUniversalTime();
                        
            
                cacheManager.Add("Hello", "World",
                CacheItemPriority.Normal,
                null,
                new AbsoluteTime(expiryTime));

            object result = cacheManager.GetData("Hello");

Aything going wrong again?
Jan 11, 2012 at 11:29 AM

Yes, var cacheManager = CacheFactory.GetCacheManager(); is equivalent to using the container in EntLib 5.

AbsoluteTime takes a local time and internally converts it to UTC.  Try that change.

 

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com