We have recently migrated from CF8 to CF10 and noticed an unexpected behavior on our cached queries.
We are a news site and have two applications on our server (CF 10, Centos 5.8 64 bits), one for the front-end to readers, and another one for administrators of the site. We made extensive use of cached queries, always with cachedwithin, and always on CFCs. When a user read an article, the query that retrieve that article is cached for 15 minutes, and if an administrator makes a change on that article, after the update we call exactly the same read query with a cachedwithin(0,0,0,0) in order to clear the cached data.
That worked fine until the upgrade to CF 10, when we realized that the calls for cleaning the cached queries were not working. After a lot of testing we noticed that if we call the cleaning cache query withing the readers application scope, then it is correctly erased from the cache for the readers. The exact same query called from administrators scope only clears the cache for the administrators, not the readers.
Reading the cache documentation I have only found references to the different scopes of ehcache, but I don't know if those scopes also applies to the cachedwithin cached queries. Also, supposedly the cache scope by default is server, not application....
So, are the queries cached with cachedwithin cached on an application scope, as it seems? Is there a way to change this in order to make them cached on a server scope? Would be better to migrate to cache functions like cachePut() and cacheRemove()?
Thanks in advance,
(please forgive my poor english, need some more practice at writing...)
This appears to be a bug in CF10.
I'm just getting a portable repro case sorted out, and will report back.
I've had more of a dig into this and documented my findings here: http://adamcameroncoldfusion.blogspot.co.uk/2012/10/probably-backwards-compat-bug-in-cf10s.html
Bottom line is that CF10 has changed behaviour here. I think it constitutes a backwards compat bug, but I think it's gotta be consigned to "well we learn something every day" rather than expecting them to change it?
Thanks you very much for you reply.
We are still trying different things, and noticed that we overlooked a very important detail: by default, CF10 uses Ehcache to cache queries, so in fact we were using Ehcache without knowing it (yes, I read the documentation, yes, I didn't understand it correctly, I thought that you can activate Ehcache as an option). We have checked the "Use internal cache to store queries" option in the Caching server settings, and after a reboot, now it seems to work as expected.
So, now, the problem seems to be (at least in our production server) that Ehcache default scope is application, not server, as one can think reading the docs. I understand that for new deployments that's not an issue, but when migrating websites with more than one application defined that use common queries, that's a bit tricky to find.
As well as making the setting in CFAdmin, one can also do it in Application.cfc:
<cfset this.cache.useinternalquerycache = true>
That is not the default, but it sets it back to work how previous versions of CF worked.
Thanks again for your time on this, Adam.
Yes, in fact I had read that page in the docs, but, I'm not sure why, I supossed that Ehcache was an option, and that by default the cache mechanism will be the old one. Also, it's not clear (not for me, at least) what is the default scope for Ehcache. I understood that it was server, but it seems to be application. I'm interested in using Ehcache, so I'll dive on the docs to look for how to change that, if possible...
Rob Brooks-Bilson very kindly point me to the correct way to achieve what I wanna do with Ehcache, in just two steps:
1- define a custom cache region. I did that in both my Application.cfc files:
<cfset cacheName = "customQueryCache">
<cfif NOT cacheRegionExists('#cacheName#')>
2- assign an unique Id to every cached query, in that region:
<cfquery name="articleList" datasource="c7_noticiasonline" cacheRegion="customQueryCache" cacheID="qAllArticles" cachedwithin="#CreateTimeSpan(0, 0, cache, 0)#">
As I usually need a cached query for every item in the table, in that cases I named the queries with the database item key:
<cfquery name="article" datasource="c7_noticiasonline" cacheRegion="customQueryCache" cacheID="qNewsDetail#IdArticle#" cachedwithin="#CreateTimeSpan(0, 0, cache, 0)#">
Defining the caches and querys in that way, I can access any cached query from any application on our website, using its region and Id.
As a bonus, in the admin section on our website, instead of calling a query with CreateTimeSpan(0, 0, 0, 0) to clear the cache, now we use cacheRemove(). More elegant, and one database hit saved.
Thanks you all for your help.