We're updating the issue view to help you get more done. 

We have PagePoolClear and componentCacheClear, but we should have a way to recompile only specific cfm and cfc files instead

Description

If you have a very busy and large CFML application with many shared components, it becomes highly likely that running PagePoolClear will cause a concurrentmodificationexception due to any other request trying to access anything in the page pool at the moment it is clear. I've ignored these errors for years since it only happens when I deploy my code, but recently I've learned that the chance of this happening can be reduced quite a bit if we reduce how many page objects are cleared. Ideally, only the cache for one site or one file can be cleared if we had a granular way to control this in CFML. I can implement that code once I have a way to do it from CFML, but Lucee doesn't have a pure CFML way yet.

lucee.runtime.exp.NativeException: java.util.ConcurrentModificationException
at org.apache.commons.collections4.map.AbstractReferenceMap$ReferenceBaseIterator.checkMod(AbstractReferenceMap.java:809)
at org.apache.commons.collections4.map.AbstractReferenceMap$ReferenceBaseIterator.hasNext(AbstractReferenceMap.java:783)
at lucee.runtime.PageSourcePool.clearPages(PageSourcePool.java:214)
at lucee.runtime.functions.system.PagePoolClear.clear(PagePoolClear.java:66)
at lucee.runtime.functions.system.PagePoolClear.clear(PagePoolClear.java:60)
at lucee.runtime.functions.system.PagePoolClear.call(PagePoolClear.java:37)

Which is dying on a fail-fast map object that you didn't or can't synchronize I guess. It is probably possible to implement some kind of try/catch delayed retry to give it a chance to recover as a way to fix it.

Without trying to fix that though, I've implemented 2 ways to handle more granular page reloading and I had to make many changes to core features, and new bytecode to do it, but it works. It is a bit spread out in my branch since I implemented cfc before cfm.

here how you could force compilation:
<cfif structkeyexists(request, 'reloadMode')>
<cfinclude template="/test.cfm" forceReload="true">
<cfelse>
<cfinclude template="/test.cfm">
</cfif>

and this new BIF for cfc files. I didn't want to interfere with createobject since it already has a lot of optional arguments.
ReloadComponent(componentInstance, onlyIfChanged); - this supports object instance, not string.

I originally wrote reloadComponent trying to eliminate the component search code to see if it would go faster, but it doesn't when caching is enabled. I do my own date check and have made forceReload parameters for loadPage() everywhere.

I don't like deploy being able to break my sites, so I'm planning on implementing these features into my CFML deploy scripts so I can have closer to zero downtime and still leverage application cache for the majority of the files to keep it fast.

Status

Assignee

Unassigned

Reporter

Bruce Kirkpatrick

Affects versions

5.3.2.16

Priority

New