Do I need to use variables (for example cache_time) to disable the cache createTimeSpan(0,0,0,0); in a local development environment, but I haven’t yet found the best way to do this for functions.
OK - I’ll try to be more explicit - so if you run your code, you get this error:
Paremeters of the function createTimeSpan have to be literal numeric values in this context
What does that mean?
Using your code as an example:
cache_days = 1;
createTimeSpan(cache_days,0,0,0)
1 is a literal cache_days is not a literal. it’s a variable.
So when it says you need to use literals, you need to actually - literally - use “hard-coded” values.
Why? Fuck knows, beyond “unhelpful implementation”. It looks to me - without looking at the source as I don’t want to entirely lose my will to live - that the timespan value is used at compile time, and they’re doing some jiggery-pokery to extract the createTimeSpan call (although that ought to be a runtime thing too), but can’t - for what are hopefully obvious reasons - can’t resolve a variable as that can only be done at runtime.
There shouldn’t be such a constraint as you allude to above, but… well… here we all are.
@AdamCameron
Yes, I’ve grasped the issue from the start.
What I’m trying to figure out is:
Is there a workaround to use cachedWithin in functions the same way it’s used in queries/cfhttp/etc., utilizing a variable instead of a literal value? (I assume not, but one never knows…)
Is this behavior intended only for functions? Perhaps someone from the Lucee team could shed light on this. At this point, I’m inclined to think this behavior is deliberate, as the same mechanics apply to ACF as well.
Due to the nature of the situation, the answers are:
no - it needs to be compile time, so you need to use literal values. That’s the long and the short of it.
yes - they’ve even documented it thus, so it’s a deliberate thing.
In your situation, I’d dispense with the Lucee implementation (which seems half-baked. And poss using the wrong recipe), and write a caching decorator and DIY.
Where are you seeing that CF supports this? It’s not on cffunction…? (This does not necessarily mean anything, as they’re patchy with keeping their docs up to date).
Late to the party, but… I’ve never been a big fan of cachedWithin on anything (http requests, functions, queries) simply because its a giant PITA to clear those caches (having to pass 0 timespan to clear).
I instead lean on cacheGet(), cachePut() and cacheRemove(), when I’m not using something like CacheBox to handle caching.
function doSomething( required struct data, boolean clearCache = false, numeric cacheDays = 90 ) {
// get the data from the cache
var myResult = cacheGet( 'myResult' );
// check if we have data in the cache, or are forcing a regeneration of the data
if( isNull( myResult ) || arguments.clearCache ) {
// meat and potatoes of my function to generate the output from the input (arguments.data)
myResult = //whatever result the function should return;
// cache the result for later use
cachePut( 'myResult', myResult, createTimeSpan( arguments.cacheDays, 0, 0, 0 ) );
}
// return myResult (either the cached version, if available, or the regenerated data from the function)
return myResult;
}
Generally speaking I have a decorator CFC that I use (similar to what Adam shows in his blog post) that has get(), set() and clear() functions, along with some other rudimentary cache management stuff so the CFC gets autowired to the component and I can make use of the functions inside the CFC instead of the native caching functions. This also lets me replace this CFC with CacheBox without a whole lot of rework and allows different caching engines to be implemented (redis, memached, etc.)
But at the end of the day the pattern is the same… get your data from cache, check if you have it or need to/want to regenerate it, put it in the cache and return the result. Either way myResult has data - either from the cache or generated during that call.
Pattern works everywhere you would use cachedWithin - you’re simply caching the result of the function (or http call or query or whatever) in a roll your own fashion vs. depending on cachedWithin and all its idiosyncrasies.
Those are great functions to clear the entire cache, but for clearing the specific cache item (in the OPs case a function) using cachedWithin… yes, it is a giant PITA.
If everything looks like a nail, then hammers are great… but for precision control over individual cache items… I’ve yet to find anything that beats the pattern I have shown.
Edit: By ‘those caches’ in my original response, I should have said those items cached with cachedWithin - which would would have clarified that I was specifically talking about clearing any one specific cache item that uses the cachedWithin attribute vs. clearing the entire cache.