[cachebox-3.6] - afterCacheRegistration with Standalone

As the title says, I’m trying to figure out how to run the afterCacheRegistration() handler when using cachebox as a standalone. There’s not much documentation on this, so not entirely sure how to get it to run. Just putting it into the config doesn’t trigger it and the couple of references in this group are with Coldbox and interceptors. Any thoughts?

Mary Jo

afterCacheRegistration is an interception point and not a handler, therefore you will need to look at writing an interceptor for that.

http://wiki.coldbox.org/wiki/Interceptors.cfm

Can you show us what you’ve put in your config as well as the code in your listener? Here is the portion of the docs that covers how to define a listener:
http://wiki.coldbox.org/wiki/CacheBox.cfm#Listeners

As the doc mentions, it follows the same format as ColdBox interceptors. You can see some actual code samples on our Interceptors doc:
http://wiki.coldbox.org/wiki/Interceptors.cfm#Configuration_File

Also, here is the portion of the docs that shows some example listeners.
http://wiki.coldbox.org/wiki/CacheBox.cfm#Cache_Listeners

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

To clarify, CacheBox actually generically calls them “listeners”. When you run CacheBox inside of ColdBox MVC, it broadcasts its events via the ColdBox IntercetproService which means you listen to CacheBox events with regular ColdBox interceptors that are registered in /config/ColdBox.cfc.

When using CacheBox in standalone mode (As MaryJo is doing) CacheBox creates its own lightweight EventManager that is a scaled-down version of ColdBox interceptors. These listeners are simply registered directly in your CacheBox config (or added programmatically to the config object).

Either way, your “listener” follows the same basic pattern: A CFC with a method named after the event you which to listen to and the class name of that CFC is registered in a config. Internally, the event manager (be it ColdBox Interceptors, or the CacheBox event manager) creates a singleton instance of that listener, inspects its methods, and calls the appropriate ones as neccessary so they can respond as events occur.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

This is the additional information I needed, thanks!

Mary Jo

So another question on this. I have my listener working and loading my caches on startup. But some of these are fairly big, slow items to cache so I wanted to run those asyncronously which the docs say you can do with a cfthread. However, when I wrap the code in a thread, then it doesn’t seem to work and the items don’t show up in cache. I’m not getting any errors from my global error handler, and if I just comment out the thread open and close everything works fine. Any ideas?

Mary Jo

`

`

Chances are, something is erroring out. Errors from within a cfthread won’t get caught by any global error handling which can be a real pain. Try putting a try/catch in the code and using logging or cfmail in the catch to send you the error message.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Sample code for this, pretty much the same as what is in the Cachebox book:

function afterCacheRegistration(interceptData){
// Get the registered cache reference from the incoming interception data
var cache = arguments.interceptData.cache;

// Only work on the catalogs cache
if( cache.getName() eq “catalogs” ){

thread name=“catalogThread” {
var catalogs = application.wirebox.getInstance(‘catalogService’).getAllCatalogsToCache();
cache.setMulti(mapping=catalogs,timeout=0);
}

}
}

compose-unknown-contact.jpg

Thanks, yeah that was it…I just had to drop my error handler into a catch block (it’s coded to work either globally or in a catch block which is handy). The error was what I suspected, so a bit of a mistake in the cachebox book example, the local var ‘cache’ was not passed into the thread where it’s used to load the cache items. Once I added that, no more errors…but sadly still nothing in cache either. So still not sure what the issue is.

MJS

Played around with this a bit more but it’s really baffling. Since I wasn’t getting any errors now, I decided to throw an email into the code after the cache.setMulti() line to make sure it was processing through to that point and dump the data that I was putting in the cache. And got the email as expected. Yet still nothing in the cache. But again, if I just remove the thread, it works fine. So pretty stuck at this point and looks like I may not be able to use this event listener for anything I want to load via a cfthread.

Mary Jo

I wonder if the cache factory or cache provider is getting duplicated in memory and the items are being added to the duplicate cache. There is a getFactoryID() method on the cacheFactory (CacheBox) object that might help you debug.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Cool, I'll look into that. I was wondering the same thing, if having to
pass the cache object into the thread is causing some referential issue
such that the data is ending up somewhere else.

MJS

Yeah, any variables you pass directly to a thread are duplicated. Anything in the variables scope will cross over, but you can’t do that for thread-safe reasons.

I think you’ll be forced to reference CacheBox directly from the application scope. You can, however pass the cache name into your thread since that’s just a string.

application.cachebox.getCache( “cacheName” )

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

wrote: Yeah, I think you’re right. I redid it that way and that does indeed work. Thanks!

Just FYI - I continue to have some issues with this. I was testing originally with my reinit function which manually reloads items in application scope. However, when I tested with a true application that had timed out, I then get errors in the threads that cachebox doesn’t exist in the application yet. It seems that the afterCacheRegistration triggers before the cachebox gets put into application scope. I tried using afterCacheFactoryConfiguration() instead but not having much more luck with that. I’m kind of ready to give up on this as this point, it just doesn’t seem to work reliably when dealing with a standalone configuration. At least running in a cfthread… I may have no choice but to run it without those and just live with the slow startup.

Mary Jo

Yep, if you look at the configure() method in CacheFactory, the scope registration of done after the caches are registered so that means it hasn’t been set in the Application scope when the caches are first added. We could change that order around, but I’m not sure it would break something else. it’s a bit of a catch 22 I’m afraid, but cfthread has always been a bit of a pain to work around.

One work around would be to persist the cache in some persistent scope manually prior to opening the thread then fetch it from that scope from inside the thread.

Another workaround, would be to not put the cache config in your config file, but use the programmatic configuration methods on CacheBox after it has been created (and persisted).

Of course, an even simpler option might simply be to create CacheBox when your application starts, then just manually run some method on the next line of code (can be asynch) that preloads some items into the cache. However, if the items in cache are necessary for your site to run does it really make sense to try and load them async anyway?

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Yeah I’ve not used cfthread a lot before (which is probably obvious from my earlier messages!) but it seemed like a good way to go to speed up the startup times particularly for development work. I think my best solution if I can’t get it to work otherwise might just be to only programmatically run this listener for production startups and forget the cfthread stuff.

Re: “Another workaround, would be to not put the cache config in your config file, but use the programmatic configuration methods on CacheBox after it has been created (and persisted).”

I assume you meant the listener… how would you do that?

Re: a manual method of running these cache startups… yeah I’ve considered doing that as well, but not sure how I’ll know when the cachebox startup is completed. I could hit a URL to load the cache during my builds, the problem is more if the servers are being restarted for any reason. As for being necessary for the site to run… none of these are necessary for the site to run, the ones that are I will load synchronously. The long-running ones are some of our top level search pages which create these big nested structs of categories and product results for each. Since they are the first page most users hit after the homepage, but also some of our slowest pages, it would be ideal to have them all cached on app startup. Typically on production users are redirected to a maintenance page if we have to restart so these aren’t pages that are going to be getting hit right away.

Mary Jo