[coldbox-3.1.0] - event & template caching

Hi guys,

To date I haven’t made much use of event or template caching and I have question before I get started. Are there any gotchas around using event caching? the site is basically a standard corporate website which also has a user account section. A number of the views within the user admin are user specific (dynamic built on data in the db) and currently do not have caching enabled on the views. I guess i’m sort of confused as to when I would want to use view caching and why/if I would want to enable event caching.

Thanks in advance.

Nolan

Depends on the application really. The only systemic “gotcha” is you can’t control cache eviction manually because you can’t set the cache keys.

As far as the application goes…

If you are serving the same content to everyone your are all done and ready to go! If you need to customize a portion of the page for individual viewers you would want to consider ways to use the cache and still serve custom content. This can be done via AJAX. For Adobe TV, most content is the same for all users but several areas of the page need to be customized to the user. I solved this problem by introducing a preProcess interception point that injects some stuff in the request scope and I do string replacements in my onRequestEnd() method of Application.cfc. So, I chose to break the framework, but, there are many ways to skin this cat.

Hope this helps the discussion.

Aaron

Nolan, to add to this, you can also use the standard OnRequestCapture interception point.

That’s what I’ve done for custom user cached content – it works like a charm!

It can be as simple as:

Basically, anything added to the requestCollection within that interception point creates a specific hash key of the event, and therefore a unique cache “version”.

So rc.companyID = session.companyID – and everyone within companyA would see the same cached version. You could even be silly and do rc.uniqueID = createUUID() – which caches every request but every request would be unique and therefore it’d never serve anything from the cache. I’m not sure why you’d want to do that, but it’s a good explanation of how it works.

Of course, you can go further into it, by caching views, viewlets, specific events etc. etc.

The only issue I’ve ever come across, and I know Aaaron has had the same issue, is using cfhtmlhead. I had to abandon using the JSMin plugin because of this.

HTH.

Tom.

Great points Tom!

I initially went the same route by modifying the Public Request Collection (RC) but ended up going with my “framework breaking” method to allow everyone to use the cached content. My use case may be different than most ColdBoxers. Some of my pages can be expensive. In fact, before I posted the update a few weeks ago average request times could fluctuate between 200ms - 600ms depending on the content requested. Now, we are running at a constant 300-350ms. In fact, about half of that time seems to be cache activity as I’m using the simple DiskStore for my template cache. Not as fast as some in memory caching but it’s allowed me to serve 30-40% cached events over almost 40,000k+ individual endpooints (this includes APIs and “pages”).

Again, hope it helps the discussion.

Aaron,

I too am using the simple DiskStore cache provider – primarily because we’ve got a non-sticky session cluster, and in order for the servers to “share” the cache, I had to use an NFS fileserver which all servers on the cluster can access natively.

I’m sure clustering ehcache would be far superior in terms of performance, from the docs Luis seemed to suggest it was easy - but the difference I saw just by enabling coldbox caching was enough for me to be more than satisfied with the improvements (at least until I have more time on my hands).

I’d be really interested (seeing as we’re on AWS) to see a cache provider written for Amazon ElastiCache. Maybe when I have more time on my hands I’ll write one myself and contribute!

Aaron,

I too am using the simple DiskStore cache provider – primarily because we’ve got a non-sticky session cluster, and in order for the servers to “share” the cache, I had to use an NFS fileserver which all servers on the cluster can access natively.

I’m sure clustering ehcache would be far superior in terms of performance, from the docs Luis seemed to suggest it was easy - but the difference I saw just by enabling coldbox caching was enough for me to be more than satisfied with the improvements (at least until I have more time on my hands).

I’d be really interested (seeing as we’re on AWS) to see a cache provider written for Amazon ElastiCache. Maybe when I have more time on my hands I’ll write one myself and contribute!

Hi guys,

Thanks for your feedback on this. I’m still confused though. Is what you discussed related to having event caching enabled or is this related to template caching. I guess i’m confused as to when/if I should enabled event caching and if I do enable will that create issues with pages that are “user” specific.

Thanks for clarifying.

Nolan

Nolan,

Template caching – or more accurately, view caching – is done within render/setView, for example setView(cache=true,cacheTimeout=90,cacheSuffix=”user_#session.userID#”).

So view caching can have “user” specific caching – if you use the cacheSuffix attribute. But you have to add that everywhere you use set/renderView, otherwise everyone sees the same cached views.

Event caching - caches the entire event and doesn’t have any options for a prefix (again, by default everyone sees the same cache) – but that’s where the onRequestCapture interception point comes in. The cache “key” for event caching is basically the handler/event name and the requestCollection serialized and then hashed – to create a unique cache “key” (I think it’s something like cbox_incomingContextHash = hash(rc.toString()) in coldbox.web.services.RequestContext). You need to use onRequestCapture (which fires before the cache is inspected) to inject values that can potentially alter the serialized/hash key.

I use a combination of event and view caching – depending on the requirements needed.

The good thing about view caching, is that you can set the timeout to be different than the standard cacheBox timeout you’ve set, and you can, as described earlier, alter the prefix to fine tune the caching properties of individual views.

Let’s say you want everything cached in your application for 15 minutes, and for everything to be based on a user’s loginID:

1.) Turn on event caching in Coldbox.cfc

2.) Cache the events in question in your handlers ().

3.) Add an interceptor (say cacheControl.cfc) and add the onRequestCapture function. Add the user ID into the rc (rc.userID = session.userID)

4.) Reinit you app.

5.) bam! You have a site-wide user-specific cache :slight_smile:

What’s more, if you set session.userID = 0 in onSessionStart, “public” users would all see the same cache before they logged in. Pretty cool.

Elsewhere in your site you may have a few views that aren’t “user” specific (why create lots of cached copies of the same thing!)?, and in those cases you may want a longer cache timeout (say 2 hours) and with no prefix. That’s where the render/setView cache comes in.

All of the examples above are obviously just quickly hacked together to demonstrate, but hopefully you get the idea

Hope that helps

Tom.

Also, to clarify, cached events are stored in the “template” cache. The same place a cached view, or viewlet would be stored.

-Aaron

Hi Tom, Aaron,

Thanks very much for the explanation. That helped a lot in understanding how event caching works. So here’s a scenario…(with event caching on)

  1. User A comes to page via an email that has some unique url variables to identify the user and the their action, the db is queried, and we set some session vars and rc vars to display in a view. the page completes rendering and the event is cached.

  2. User B gets the same email but again, with unique url vars, the page renders and that event is cached.

Since they’re both hitting the same handler (event), does User B get served up the cached event from User A or does it become a unique cached event for User B because there are different RC vars in the request?

Thanks again.

Nolan

They will be the same if the rc variables are the same. If they are different, then it is a different permutation. Also, you could mix in via onRequestCapture() for THAT specific event, more variables to make it unique.

Luis F. Majano
CEO
Ortus Solutions, Corp
www.ortussolutions.com

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

Social: twitter.com/lmajano facebook.com/lmajano

They’d see different things due to the way url parameters get automatically injected into the request collection. Luis I’m sure could confirm that.

For example /news?page=1 and /news?page=2 would be different cached events.

If we used your example, let’s elaborate slightly further, without using onRequestCapture:

  1. User A comes to page via an email that has some unique url variables to identify the user and the their action, the db is queried, and we set some session vars and rc vars to display in a view. The page completes rendering and the event is cached.
    User A is welcomed with “Hello Bob”.

  2. User A is then redirected after 5 seconds to /account/myaccount/balance (which runs a model method that grabs his account balance based on the session vars you setup earlier).

  3. He sees “Hello Bob, your account balance is $33”.

  4. User B gets the same email but again, with unique url vars, the page renders and that event is cached.
    User B is welcomed with “Hello Jim”
    So far so good, right?

  5. You B is redirected to /account/myaccount/balance – where he sees “Hello BOB, your account balance is $33” (!!)

Hopefully that makes sense.