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.

Activity

Show:

Zac Spitzer 25 March 2021 at 22:35

Hi Bruce, can you file a PR ?

Bruce Kirkpatrick 4 December 2018 at 19:51

cfinclude change:
https://github.com/brucekirkpatrick/Lucee/commit/2352b2b4d0e2c842fc561c927ca500dac05151aa

this commit has reloadComponent, but it also has a few lines of debug stuff I did at the same time.

https://github.com/brucekirkpatrick/Lucee/commit/be46e2d575daec37b9f553b10b3dc938f53537ca

An idea worth sharing.

Details

Assignee

Reporter

New Issue warning screen

Before you create a new Issue, please post to the mailing list first https://dev.lucee.org

Once the issue has been verified, one of the Lucee team will ask you to file an issue

Affects versions

Priority

Created 4 December 2018 at 19:46
Updated 25 March 2021 at 22:35