ObjectBroker is FarCry’s internal cache management system.
It is used to cache content objects (ie the data of each content item) and webskins (aka views). In FarCry 7.0, friendly URL and dmNavigation/dmCategory alias lookups were added. With this most recent change, all FarCry core caching including arbitrary cache namespaces is handled by the ObjectBroker.
The ObjectBroker service is managed by the ./packages/lib/objectbroker.cfc
component, and it’s behaviour can be extended or overridden by plugins. So far we have had a lot of success storing FarCry caches in EhCache servers, Memcache and Amazon ElastiCache clusters.
Configuration
You can set up any number of cache namespaces on application initialisation from your ./config/_serverSpecificVarsAfterInit.cfm
config:
<cfset maxObjects = 10000 />
<cfset cacheTimeout = 3600 />
<cfset application.fc.lib.objectbroker.configureType("myCacheNamespace", maxObjects, cacheTimeout) />
<cfset application.fc.lib.objectbroker.configureType("myCacheUnicorn", maxObjects, cacheTimeout) />
<cfset application.fc.lib.objectbroker.configureType("myCacheRainbow", maxObjects, cacheTimeout) />
Using ObjectBroker
Setting cache content
Example for caching the result of a search using url.q
as the filter:
<cfset key = "query-" & rereplace(url.q, '[^\w]+', '-', 'ALL') />
<cfset data = { q=qSomeResult } />
<cfset application.fc.lib.objectBroker.AddToObjectBroker(data, "myCacheNamespace", key) />
Notes:
- The data must always be a struct, even if it only has a single item
- The data must be serializable to / deserializable from JSON - no components or Java objects
- The cache key must only contain alphanumeric characters and hyphens
Getting Cache Content
Example for getting the cached search results:
<cfset key = "query-" & rereplace(url.q, '[^\w]+', '-', 'ALL') />
<cfset stResult = application.fc.lib.objectbroker.GetFromObjectBroker(key, "myCacheNamespace") />
<cfif structIsEmpty(stResult)>
<!--- Data is not in the cache --->
<cfelse>
<!--- Use cache result here --->
</cfif>
Notes:
- If an item is not in the cache ObjectBroker will return an empty struct.
Removing Items From ObjectBroker
Example of removing data from the cache.
<cfset key = "query-" & rereplace(url.q, '[^\w]+', '-', 'ALL') />
<cfset application.fc.lib.objectbroker.RemoveFromObjectBroker(key, "myCacheNamespace") />
Best Practices
Cache Usage Should be Transparent
The process of checking the cache for data, and adding a cached value if there is none, should be encapsulated in a function. Developers using your functionality should not need to know about ObjectBroker. A lib, e.g. packages/lib/mysearch.cfc
, or a content type component is a good place to put that function.
Allow the Developer to Skip the Cache
This gets us all - we waste time troubleshooting an issue and not seeing results, only to realise that the page had been in the cache the whole time. FarCry has a setting to disable caching in the tray; you can use that setting too.
When the caching is disabled FarCry sets request.mode.flushcache
to true
.
Complete Example
In this example, I have encapsulated the search examples we’ve been using so far.
<cffunction name="getResults" returntype="query" access="public" output="false">
<cfargument name="filter" type="string" required="true">
<cfargument name="bFlushCache" type="boolean" required="false" default="#request.mode.flushcache#">
<cfset var key = "query-" & rereplace(arguments.filter, '[^\w]+', '-', 'ALL')>
<cfset var data = application.fc.lib.objectbroker.GetFromObjectBroker(key, "mysearch") />
<cfif arguments.bFlushCache or structIsEmpty(data)>
<cfset data.result = application.fapi.getContentObjects(typename="dmHTML", title_like="%#arguments.filter#%") />
<cfset application.fc.lib.objectBroker.AddToObjectBroker(data, "mysearch", key) />
</cfif>
<cfreturn data.result />
</cffunction>
<cfset qResult = application.fc.lib.mysearch.getResults("home") />