Friday 1 March 2013

Weirdness with interface caching: can someone sanity check this please?

G'day
I was going to troubleshoot something I read somewhere about someone having some issues with interface caching. That sounds vague, but I don't have the URL on me at the mo', and haven't got far enough to really comment on it yet.

As part of the investigation I knocked together some code, and I am seeing "unexpected results" from my baseline testing.


Here's the code:

// ITestTrustedCache.cfc
interface {

    public string function f(required string s);

}

// TestTrustedCache.cfc
component implements="ITestTrustedCache" {

    public string function f(required string s){
        return ucase(s);
    }

}

<!--- testTrustedCache.cfm --->
<cfscript>
o = new TestTrustedCache();
writeOutput(o.f("hello world<br />"));
</cfscript>

What I have here is an interface that requires a method f(), a CFC which implements the interface and correctly implements f(). I run the code, and it works predictably, outputting "HELLO WORLD".

But what I was wanting to test was what happens when the trusted cache is switched on. I did this:
  1. Switch trusted cache on in CFAdmin
  2. hit testTrustedCache.cfm. It runs fine.
  3. alter ITestTrustedCache.cfc, thus:

// ITestTrustedCache.cfc
interface {

    public string function f(required string s);

    public string function g(required string s);

}

So I've added in another method. Note that TestTrustedCache.cfc does not have this method, so strictly speaking it now breaks its contract with ITestTrustedCache.cfc. But because the trusted cache is switched on, ITestTrustedCache.cfc won't be checked for changes, and the code should still run. And indeed this is the case. So that's fine.

Now I do this:
  1. switch off trusted cache;
  2. "Clear Template Cache Now";
  3. "Clear Component Cache Now";
  4. hit testTrustedCache.cfm.
Now I would expect this to error with this:

CFC cf.cfml.tags.extensibility.interface.TestTrustedCache does not implement the interface cf.cfml.tags.extensibility.interface.ITestTrustedCache.

The g method is not implemented by the component or it is declared as private.

However it still runs fine, so CF is not checking ITestTrustedCache.cfc for changes even after the trusted cache is switched off, and the template and component caches are cleared. This seems like a bug to me..?

Thinking it's always best to first blame one's own code before blaming ColdFusion (it might not seem that way from what I write, but it is my general approach), I decide perhaps I'm misunderstanding how the cache-clearance / template rechecking works. I hypothesise that perhaps because the interface file's timestamp changed whilst the caching was on, but hadn't changed since the caching was switched off then CF might not notice the change. This is clutching at straws a bit, but easy to check.

So now I do this:
  1. switch trusted cache back on again;
  2. hit testTrustedCache.cfm (it runs fine);
  3. modify testTrustedCache.cfm thus: 

<!--- testTrustedCache.cfm --->
<cfscript>
o = new TestTrustedCache();
writeOutput(o.f("hello world<br />"));
writeOutput(o.f("hello world again<br />"));
</cfscript>

  1. re-hit testTrustedCache.cfm: it still just shows "HELLO WORLD" because trusted cache is on;
  2. switch trusted cache off;
  3. re-hit testTrustedCache.cfm: it immediately shows "HELLO WORLD AGAIN" as well.
So that theory is out the window. The sequence of cache-on / browse / code changes / cache-off / browse is the same here as it was for the interface change, yet CF picks up the change to the CFM immediately.
Maybe it's a difference between CFM and CFC files, so I repeat the whole process, this time changing TestTrustedCache.cfc (note that's the component, not the interface). And this change is - again - reflected as soon as I switch the trusted cache off.

So now I am more inclined to conclude it's a bug with how CF checks for changes to interface files?

This is all on CF9.0.1.  I performed the initial change-the-interface test on Railo 4.0.0.013, and it behaved as I'd've expected: changes are picked up as soon as the trusted cache is switched off.

Can someone else try this on their rig, or just mentally desk-check it to see if my conclusions are correct, or whether I'm missing something? Cheers.

Righto.

--
Adam