Shouldn't the "cached" result key really be split into "fromCache" and "wasCached"?

Continuing the discussion from In which scope would you store a cachedWithin query within a function?:

I’d said earlier in the thread, replying to Jason/philllyun that:

Here’s that follow-up comment:

While we’re on that topic (of what a dump of the results of a query shows, if cachedwithin or cachedafter are used), I’ll share that I have long felt that Adobe (and Lucee, following their implementation) made an unfortunate choice in the name of result struct key being the words “cached”.

Sure, as long-time CFML devs would know, we accept that telling us “did the result come from cache?” (because it’s false when we first run something that’s “to be cached” and true when it came from cache).

But of course the English syntax implied by that keyname “cached” would be read more naturally (and by many folks) to indicate “was the query cached after running the query?”. But that’s NOT in fact what it tells us (because, again, the first call would say “false”). Again, repeating the same query within the cached time would return “true”, which is telling us it “came from cache”.

So in fact, last year I created a tracker ticket with Adobe proposing that this should be split into two new keys, wasCached and fromCache–because there really are cases where use of cachedwithin (or cachedafter) may return true or false for either.

I give an example and more discussion in the bug report. But I noticed just today that I made a pretty grave mistake in my first two paragraphs after the code example there, referring in my words to a q2 and q3 when instead the code has only queries named cq1 and cq2. Doh! I’m sure that confused some when they may have seen the bug report. It was just a mistake in translating a more elaborated working set of examples into that simple pair I showed there.

So if any of you may go there now, please keep that in mind. And that’s why I’ve held off offering that tracker URL until now. :slight_smile:
https://tracker.adobe.com/#/view/CF-4212124

And before posting this, I figured how to split this off as a new topic, leaving a breadcrumb in the original thread. This new discussion seems within the realm of the other thread, but I didn’t want to clutter that other thread with this.

Words are hard. I like the idea although wasCached is still confusing to me.
I see more interpretations:
“This was cached and may not be anymore due to expiration”
“This data was cached and this result came from the cache”
“This was added to the cache after processing the query”

I’ve borrowed from your ACF proposal and created a (works on lucee) interpretation / variation:

<cfscript>
	qry = queryNew(
		"name,created",
		"", // ignore types
		[
			["foo",now()],
			["bar",now()]
		]
	);

	loop times=5 {
		cached_qry = queryExecute(
			"SELECT name,created FROM qry", 
			[], // no queryparams needed
			{	dbtype="query",
				cachedWithin=createTimeSpan(0,0,0,1),
				result="cached_qry_result"
			}
		);

		writeoutput("Cached : #cached_qry_result.cached# <br/>"); 
		sleep(334) // nap for ~1/3 second
	}
</cfscript>
	/* Currently: I see cached = "false" for the first iteration, "true" while it was cached, and "false" again when it expired 
		Cached : false
		Cached : true
		Cached : true
		Cached : false
		Cached : true
	*/

	/* Desired: I see cached = "true" on all iterations (caching was used) AND I see information about the state of the cache
		Cached : true  ,  fromCache : false  , setCache : true
		Cached : true  ,  fromCache : true  ,  setCache : false
		Cached : true  ,  fromCache : true  ,  setCache : false
		Cached : true  ,  fromCache : false  , setCache : true
		Cached : true  ,  fromCache : true  ,  setCache : false
	*/

Personally I like the idea of more information about the cache state, no matter what we call it.
get/from
set/to/was

I also like the idea of a TTL remaining (for cachedWithin type of timespan) although that gets confusing for “request” and cachedAfter.

@carehart , you raise an important point. It’s not just a matter of words. It’s also got to do with cleanliness in design, That will in turn have an underlying impact on ease of learning, ease of implementation and how the language evolves.

What is cachedWithin cfquery or queryExecute actually designed to do for you?

  1. Get the query from cache, if a copy of it is alive and available in cache; otherwise get it from the datasource?
  2. Get the query from cache, if a copy of it is alive and available in cache; otherwise get it from the datasource and cache a copy of it for the given time span?

Some other?
As I see it, the answer is cfquery’s or queryExecute’s contract with you.

The option 1. doesn’t care who puts the query in cache. I only found out that this is a viable option in Lucee after asking the question, In which scope would you store a cachedWithin query within a function?

For this option, a response struct containing fromCache: true or fromCache: false will tell you what you need to know. According to the contract, that is.

It seems to me that the responses “cached”, “isCached”, “wasCached”, and the like, pertain to option 2. As Charlie has explained, the use of the past tense leads to all sorts of inconsistencies.

Let me add another point to that. Option 1. is OK as design. The service has just one responsibility. Whereas option 2. is bad software design. There the service has more than one responsibility.