Railo 4.0 Previews: Cached Functions

May 29, 2012 · By Mark Drew · 13 Comments

In this first post of the Railo 4.0 previews, we are going to focus on the Cached Functions feature. In Railo 4.0  you can cache your functions and methods in a CFC, so that after the first request the results and output are  obtained from cache rather than re-evaluated each time. 

Let's look at an example.

Take the following code in CacheDemo.cfc:

component {
   function getTime(String name, Numeric age)
         cachedwithin="#createTimeSpan(0, 0, 0, 10)#" {
      return Now() & " " & arguments.name & " " & arguments.age;
   }
}

You can see that we have added the argument cachedwithin to the getTime function, when we call this multiple times, we will get the same result, as now the output and result of the method are cached!:

<cfset comp = new cfcs.CacheDemo()>

<cfdump var="#comp.getTime()#" label="Inital call">
<cfset sleep(1500)>
<cfdump var="#comp.getTime()#" label="Cached call">

<!--- now with attributes --->
<cfdump var="#comp.getTime("Elvis", "29")#" label="Inital call">
<cfdump var="#comp.getTime("Sean", "42")#" label="Inital call">
<cfset sleep(1500)>
<cfdump var="#comp.getTime("Elvis", "29")#" label="Cached call">
<cfdump var="#comp.getTime("Sean", "42")#" label="Cached call">

Results:

You can even cache a call to function within a page, not just components:

<cffunction name="cacheTest" cachedwithin="#CreateTimeSpan(0,0,1,0)#">
   <cfreturn Now()>
</cffunction>

<cfdump var="#cacheTest()#" label="Initial Call">
<cfset sleep(1500)>
<cfdump var="#cacheTest()#" label="Cached Call">

Results:

Tags: Preview · Railo 4.0

13 responses so far ↓

  • 1 Michael Zock // May 29, 2012 at 4:41 PM

    In case this is built on top of Ehcache or something similar, will it be possible to specify which cache instance is supposed to be responsible (e.g., for those of us who use both, a local instance and a dedicated network cache)?
  • 2 Gert Franz // May 29, 2012 at 4:48 PM

    Yes, for this purpose the admin now has an additional cache source "functions" which allows you to determine where the function should be cached in. You can select any of the custom defined caches there. No matter whether they are clustered or not...

    Gert
  • 3 Mark Drew // May 29, 2012 at 4:50 PM

    As Gert said, by default it will be the RAM cache but you can define any cache provider as a location to store these items.
  • 4 Gert Franz // May 29, 2012 at 4:58 PM

    An important addition is, that the key Railo 4 uses to define the cache entry is the hash value of the arguments passed to the function.
  • 5 Michael Zock // May 29, 2012 at 5:13 PM

    Thanks for the quick reply.

    I was actually thinking one step further, combining the feature above with the freedom offered by Railo's "cacheName" attribute for the "cachePut()" method.
    A local cache and a clustered one, one of them set as default and the optional attribute will take care of the rest, depending on what the situation requires.
  • 6 Gert Franz // May 29, 2012 at 5:19 PM

    @Michael: This addition makes sense and as I know our core team, we will pick that one up as well. But for now the cache set in the admin will be the target one.
  • 7 Michael Zock // May 29, 2012 at 5:30 PM

    Thanks! Even without that it sounds like a great addition.

    And you guys have already made my year anyway, since the extended Java features will allow for a more streamlined use of Collections within Railo applications. ;)
  • 8 Josh Olson // Jun 4, 2012 at 6:32 PM

    Awesome! Question:

    Does this support complex arguments that /look/ the same? That is, does the second call return the cached value? What about references to the same object (result3).

    var complex1 = [{ test = 1 }, { test = 2 }];
    var complex2 = [{ test = 1 }, { test = 2 }];
    var result1 = myFunctionWithCachedWithin(cx1);
    var result2 = myFunctionWithCachedWithin(cx2);
    var result3 = myFunctionWithCachedWithin(cx1); // note cx1
  • 9 Serge // Jun 7, 2012 at 3:15 PM

    Hello Merk.
    Why cachedwithin="#createTimeSpan(0, 0, 0, 10)#" is used in example and not cachedwithin=createTimeSpan(0, 0, 0, 10)?
  • 10 Michael Offner // Jun 7, 2012 at 5:07 PM

    @Michael
    Like Gert has written before, you can define a cache for functions in admin, BUT in addition you can also define a cache in the application.cfc:
    this.cache.function="myCache";

    and a attribute "cacheName" for the tag cfquery is already on my toDo list ;-)

    BTW:
    you can also define
    this.cache.resource="myResourceCache"; // cache used for Ram Resource
    this.cache.query="myQueryCache"; // cache used cfquery
    this.cache.object="myObjectCache"; // cache used for cachePut,cacheGet ...
    this.cache.template="myTemplateCache"; // cache used for template caching
  • 11 Michael Offner // Jun 7, 2012 at 5:09 PM

    @Josh
    no only simple types atm, perhaps we will open this a little bit in the future
  • 12 Michael Offner // Jun 7, 2012 at 5:13 PM

    @Serge
    in CFML this:
    cachedwithin=createTimeSpan(0,0,0,10)
    is equal to
    cachedwithin="createTimeSpan(0,0,0,10)"
    and not
    cachedwithin="#createTimeSpan(0,0,0,10)#"

    cachedWithin need a timstamp as input, not a string, that need to be evaluated to a timestamp, you can also define a number, this can be converted to a timestamp.
    this
    cachedwithin="1"
    is equal to
    cachedwithin="#createTimeSpan(1,0,0,0)#"
  • 13 Michael Zock // Jun 7, 2012 at 5:15 PM

    Thanks, Michael.

    You do realize that you're bound to give the Adobe guys an inferiority complex, right? ;)

Leave a Comment

Leave this field empty: