session based i18N view cache

Hi all,

I'm hoping to get some tips on how to make better use of the Coldbox
cache. Currently I have a view "template_head" which is translated in
to English and French. I've set this line in my preHandler:

this.EVENT_CACHE_SUFFIX = getFWLocale();

now my assumption is that when I hit the cached view, then change
locale and hit it again I should have two entries turning up in the
view cache. I'm only seeing one though (no suffix). Am I meant to see
the suffix in the cachebox content report?

eg: cbox_view-layoutsnippets/template_head

I expected to see
cbox_view-layoutsnippets/template_head_EN
cbox_view-layoutsnippets/template_head_FR

... or something similar

Obviously there's more I need to do, but I'm not sure exactly what --
any advice from the experts?

cheers
CC

that only works if your handler is not cached as if the handler is cacehd then it will never change.

I have to dig in to see what is the best way to alter the event caching for custom additions.

Luis F. Majano
President
Ortus Solutions, Corp

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

Thanks Luis -- any assistance would be greatly appreciated! My
application is at the very early stages, so if there's a best practice
here then I'm all ears!

I'm unclear as to exactly what the implications of caching (or not
caching) the handler are. I assume that the handler object is created
and held in memory until cache is dropped, so turning OFF the cache
means the handler object is created every request?

In a caching scenario I would understand the value in THIS scope not
getting updated if it was declared in a constructor, but preHandler
fires every request. Or... is that WHY it must not be cached (because
the THIS scope is being modified by a request, thus we don't want to
pollute someone else's cache)?

Is recreating my handler every request very expensive? This would
apply throughout my entire application (every handler).

In my scenario (different users, different locales per session) is it
possible to use the built in caching metadata or do I need to "roll my
own" using calls to getOCM?

a quick update on this -- while a bunch of articles refer to the
setting of this.EVENT_CACHE_SUFFIX I wasn't able to find any
discussion on WHERE to set it. After some experimentation I determined
that you need to stick it in the init() method on the handler

  <cffunction name="init" access="public" returntype="any"
output="false">
    <cfscript>
      // set event cache suffix for multi-lingual caching
      this.EVENT_CACHE_SUFFIX = getFWLocale();
      return this;
    </cfscript>
  </cffunction>

you can't put that code in the pseudoconstructor since the method
getFWLocale doesn't exist until the object is created and decorated.

Hope that helps someone else.

I have this working now -- there are probably better/tidier ways of
doing it (feedback most welcome) but for what it's worth:

In your handler declare an init method if there isn't one already

        <cffunction name="init" access="public" returntype="any"
output="false">
                <cfscript>
                        // set event cache suffix for multi-lingual
caching
                        this.EVENT_CACHE_SUFFIX = getFWLocale();
                        return this;
                </cfscript>
        </cffunction>

This takes care of caching at the locale level. If you have content
that isn't user specific but IS locale specific (say a common header
which has language elements in it) then this is all you need.

To go one step further and make it specific to a session (for example
a header which says "Welcome {Username}") you need to cache at the
view level. I decided not to append my session ID to the event cache
suffix as that would remove the ability to cache once for ALL users,
not just one.

Declare an onRequestStart event handler if there isn't one already
(coldbox config). Insert these two lines:

// set cache suffix for this user
prc.userCacheSuffix = "_" & getFWLocale() & "_" & session.sessionid;
prc.userCacheTimeout = 40; // minutes

that will result in a string you can use as a cache suffix which will
be unique for a given session/locale combination. I set the timeout to
40 minutes since my sessions time out in 30... I figure that's safe.

To cache a view you need to specify the cacheTimeout and cacheSuffix
arguments:

#renderView(view='layoutsnippets/template_header', cache=true,
cacheTimeout=prc.userCacheTimeout, cachesuffix=prc.userCacheSuffix)#

If you open up the cachebox monitor now any view you cached using the
above method should have an entry like this in the TEMPLATES cache:

cbox_view-layoutsnippets/
template_header_en_us_8efbf6b9602070995344f01dc59d2093_13900_96287697

If there's a nicer/better/easier way of doing this I'm all ears, but
this appears to work ok.

oobi,

Interesting timing, I have spent most of today pulling my hair out
trying to get my events to cache in both languages...

I guess I don't understand where to put the event_cache_suffix. I
have tried it in my init, in the prehandler, but to no avail, since
the event caching fires before then.

What is interesting is that if i set my locale to en_US, then hit a
non-cached page, the event cache name has "en_US" in it. Then if I
change my locale to "en_ES" my cache name changes to have "en_ES" in
it. But when I hit the page that was previously cached, it doesn't
create a new cached page, it just outputs the old one.

I am going to try to set it in an interceptor preProcess function to
bypass the event caching. I'll report back...

Thanks!

Ken,

If you don't cache the handler, but do cache the event, this should work. If the handler is in cache and the suffix has already been set, it will used the cached handler and then the cached event and thus never change.

To answer a question earlier on the impact on performance of not caching handlers, the answer of course is it depends. If you are autowiring up a ton of stuff of doing a lot of processing on handler creation, then the impact could be large. If you aren't, then the impact will be small.

Hope that helps,

Curt Gratz
Computer Know How

Totally makes sense, thanks Curt.

This will help out for all event caching mechanics: https://coldbox.assembla.com/spaces/coldbox/tickets/1107-new-interception-point–onrequestcapture

You can now intercept once the request is captured but before the flash ram is inflated, debug mode detection and event caching is matched.

So you can build an interceptor that adds the user’s locale or session to the event rc collection. This will give unique identity to event caching requests and easily have event caching now that is user based or whatever you want based.

Luis F. Majano
President
Ortus Solutions, Corp

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

This will accomplish something similar to what I had in mind for this ticket

https://coldbox.assembla.com/spaces/coldbox/tickets/995-cache-dependon-idea-for-event-caching

only instead of with meta data, you would use the interception point. Maybe the two could be combined as the meta data “dependsOn” is slick I think and in line with what the cfcache tag has.

Curt

What would be kind of cool in a future release would be to add a method to a handler like getCacheSuffix() which by default returns this.EVENT_CACHE_SUFFIX. If the caching engine were to run this method at the start of each request to get the cache suffix, (rather than using the public property that is set only at init), then you could simply override it to return whatever you wanted. That would allow you to cache the handler and still get your per-request cache keys.

just a thought…

Good ideas guys.

We need to develop more these ideas for 3.1

As of now, the onRequestCapture interceptor can do the trick, plus it is a great interceptor that never existed before. This gives developers the chance to alter the incoming variables and procedures before flash RAM is inflated, event detected and event caching determined.

Luis F. Majano
President
Ortus Solutions, Corp

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

Luis if you get a moment would you be able to whip together a quick example of how that onRequestCapture interceptor can be used to modify the cache key? It sounds like it might be exactly what we’re after.

component{

function onRequestCapture(event,interceptData){
// add user’s locale to request collection for event caching purposes
event.setValue('userLocal", getfwLocal());
}

}

Too difficult or too much code? :slight_smile:

Luis F. Majano
President
Ortus Solutions, Corp

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

Nice :slight_smile: In my case it’d be this: (since i need to make use of the session ID also)

function onRequestCapture(event, interceptData){

// add user’s locale to request collection for event caching purposes
event.setValue('userLocale", “" & getfwLocale() & "” & session.sessionid);
}

that’d take care of VIEW caching since you can set a cachekey, but what about events? Or is this not necessary?

this is for event caching, as for view caching you have the cachesuffix you can manipulate programmatically.

Luis F. Majano
President
Ortus Solutions, Corp

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

Sorry I’m being really thick I know – so you’re saying that if you implement that interceptor you would now be able to set this.EVENT_CACHE_SUFFIX = rc.userLocale in the handler init method to sort out the event cache?

what I am saying is that you won’t need to set that. All you need to do is add something specific to the request collection and the event will be unique because of that. Event caching works on the premise of creating a snapshot of the incoming request collection. If they are different, then it is a new cacheable event.

Does that make sense.

Luis F. Majano
President
Ortus Solutions, Corp

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

Thanks Luis! This is great stuff.

perfect, Thanks Luis