November 21, 2009
When using the template cache in ColdFusion 9, you have two main options for getting pages and page fragments out of the cache – time based expiry and flushing. This blog post covers both. You should not that all of the examples here cache full pages. In most cases, the techniques discussed can be applied equally to page fragments.
Expiring Items in the Template CacheIt's also possible to set expiry periods for items in the template cache. Here, you have two optional parameters built in to the cfcache tag to help you expire pages and fragments from the cache based on time periods. The two parameters you can use are idletime and timespan. Idletime lets you specify a period of time after which to flush the cache if the cached item has not been accessed. In other words, if the cached item hasn't been accessed in the time period specified by idletime, the item will be removed from the cache. Here's an example that caches a page and will flush it after 30 seconds of inactivity:
I'm dynamic. The time is currently #timeFormat(now(),'hh:mm:ss')# </cfoutput>
If you run this code and then run it again, you'll see that the timestamp for the page is cached. Now wait for 30 seconds or so and reload again. You should see that the time has updated.
The timespan parameter lets you specify a period of time after which the cached item should be flushed regardless of whether it's ever been accessed or not. This basically lets you say "keep this page in the cache for 30 seconds". Here's an example:
This code sets a timespan of 30 seconds. If you run the code then run it again, you'll see that the timestamp gets cached. Go ahead and keep hitting the reload button on your browser every few seconds. After 30 seconds have gone by, the timestamp will update as the old content is flushed from the cache.
Flushing Items from the Template CacheIn addition to time based expiry, you can also manually flush both pages and page fragments from the template cache using the cfcache tag. Here's an example:
There are a couple of things to note here. First, when you call this code, it flushes all templates in the template cache for your application, not just the page you call it from. Let me repeat that. Using the cfcache tag with action="flush" causes the template cache to flush all of the content for the current application. You need to be very careful using this as it's possible that on a high traffic site with a large template cache you could bring your server down when hundreds or thousands of requests hit at the same time for uncached data, causing your system to queue up requests while it's busy rebuilding the cache. In most cases what you'll want to do is to flush a single page or perhaps a group of related pages from the template cache.
So, how do you go about flushing a single page or a group of related pages from the template cache? There's another parameter of the cfcache tag you can use called expireURL just for this purpose. Let's consider an example of how we would use this:
<cfcache action="flush" expireURL="*.cfm?productID=#URL.productID#">
<cfparam name="URL.productID" default="0">
<cfcache action="serverCache" usequerystring="true" timespan="#createTimeSpan(0,0,5,0)#">
Welcome to the page for product ID #URL.productID#<br />
Timestamp: #timeFormat(now(), 'hh:mm:ss')#
Go ahead and run this example in your browser. You should have something on your screen that looks like this:
Welcome to the page for product ID 0
Reloading the page should return the same timestamp over and over as the template is cached after the first call. Now try adding the URL parameter ?productID=72 to the URL string in your browser and reload the page a few times to get the new version of the page into the cache. Try changing the value of productID a few more times, each time reloading the page so that we get a handful of pages in the template cache. Now try dumping the contents of the template cache by running this code in a separate ColdFusion file:
You should see a bunch of different entries – one for each unique productID you provided in the URL. Now go ahead and call the code we've been working with for this example, only this time append ?productID=72&flush to the URL. Go ahead and reload the page with those URL parameters a couple times. Notice the timestamp updating each time you reload? That's because passing in the URL parameter flush calls the ColdFusion page to call the cfcache tag with expireURL="*.cfm?productID=#URL.productID#". The expireURL parameter lets you specify a wild carded URL pattern such that only pages that match the pattern get flushed. This allows you to get as generic or as specific as you want in determining exactly what pages to flush. In this case we're telling ColdFusion to go ahead and flush any cached .cfm pages that have the URL parameter ?productID equal to the value that we pass in on the URL.
If you dump the contents of the template cache you'll notice that there's still an entry for the item(s) we just flushed. That's because the code in the example we've been running repopulates the cache immediately after the flush. If you didn't want the cache repopulated immediately after flushing the content, you could just as easily locate the code to flush the cache elsewhere and just remove the item.
If you want to remove a group of related pages from the cache, say all of the pages that have a productID, you could modify the code to wildcard the productID parameter like so:
This should result in the removal of all pages from the cache that have a productID URL parameter. Note that if you run this right now in ColdFusion 9.0 it will not work. There is a bug in ColdFusion 9.0 with the wildcard feature. If you put the flush code in a separate template and run it multiple times, what you'll see is that one page at a time is flushed from the cache instead of all of the pages that match the URL pattern at once. Credit goes to Aaron West for catching this bug.
That about wraps up everything I have to say about expiring and flushing pages and page fragments from the template cache. In Part 9 we'll talk about one last feature of the template cache – Dependent Caching.