Have you ever wanted to set up a section of code that will only execute once a day or once a week? You can use the <cfschedule> tag to run a ColdFusion template at scheduled intervals, but there is another method that is in many ways more flexible because it works with a section of code on a page. The technique demonstrated in this article essentially runs a piece of code on your page at intervals, acting almost as a cache — in fact, it can be used as a cache or just as a scheduled execution. There can be many applications of this:

These are only a few applications of the technique. This is not designed to take the place of query caching, which allows you to keep the results of a query in server memory for a specified length of time. It is also not designed to take the place of <cfcache> or <cfschedule>. There are many applications where those tags are exactly right for the job. This is a different technique to add to your arsenal for specific tasks.

Creating the Application Variable

The concept is to set an application variable with the current time. Code is executed if the time in the application variable reaches a date that is a specified interval in the past. For example, if you set an application variable with the current time, then test for current time plus 24 hours, you can execute code after that 24 hours passes. To demonstrate, I'll use an actual example from my site, www.tom-muck.com, that displays my most recent Community MX articles.

NOTE: You must have application variables enabled in order to use this technique. Application variables are enabled by creating an Application.cfm file in your site. For more info, consult the ColdFusion documentation at http://livedocs.macromedia.com/coldfusion/6.1/htmldocs/shared39.htm#wp1185482. Application variables have a timeout that is set in the CF administrator. Typically it is set for about 7 days.

The interval code can go on any page. The code is as follows (interval code is highlighted):

<!--- What interval measurement ("d" for days, "h" for hours, etc) --->
<cfset theInterval = "d">
<!--- How many units --->
<cfset theIntervalLength = "7">
<cflock scope="application" type="readonly" timeout="5">
   <cfif NOT isdefined("application.executeit") OR
   datediff(theInterval, application.executeit, now()) GT theIntervalLength>
     <!--- If the interval has been reached, set a variable --->
     <cfset setit = "true">
   </cfif>
</cflock>

<!--- If the variable is set, execute some code --->
<cfif isdefined("setit")>
   <cflock scope="application" type="exclusive" timeout="5">
      <!--- First, reset the time for a new interval --->
      <cfset application.executeit = now()>
   </cflock>
   <!--- execute the following code once every interval --->


  <cfinvoke
    webservice="http://www.communitymx.com/services/cmxfeed.wsdl"
    method="searchContent"
    returnvariable="aObjectArray">
    <cfinvokeargument name="search" value="tom muck" />
    <cfinvokeargument name="anyWords" value="false" />
    <cfinvokeargument name="exactPhrase" value="false" />
    <cfinvokeargument name="contentType" value=0 />
    <cfinvokeargument name="contentDate" value=60 />
    </cfinvoke>
  <cflock scope="application" timeout="5" type="exclusive">
    <cfset application.articles = aObjectArray>
  </cflock>

</cfif>

The code above reads and sets application variables, so we use the <cflock> tag to ensure the integrity of the data. If the variable doesn't exist yet (such as when the variable times out or when the server is restarted) the code will run. If the application.executeit variable and the current time is greater than the interval, the code will run also. This allows me to query the web service once a week for the latest results. I then display the results with the following:

<cfif arraylen(application.articles) GT 0>
  <h2>My latest articles at Community MX</h2>
  <cflock type="readonly" scope="application" timeout="5">
    <cfset aObjectArray = application.articles>
  </cflock>
  <cfloop from="1" to=#ArrayLen(aObjectArray)# index="i">
    <cfoutput>
    <p><a href=">#aObjectArray[i].URL#">#aObjectArray[i].Title#</a></p>
    </cfoutput>
  </cfloop>
</cfif>

Conclusion

There are many ways to cache code and execute code at intervals. This article demonstrates one way that uses a simple application variable.