Having worked a lot with the Caching Framework we all use, and held talks about it, I would like to propose to make some changes to the current CF in order to improve cache handling in the future
Status Quo
the current pattern to cache some content (VariableFrontend) is the following:
$cF = GeneralUtility::makeInstance(CacheManager::class)->getCache('identifier');
if (! $content = $cF->get($key)) {
// do expensive stuff and write it to $content
$cF->set($key,$content,['tag1','tag2'],86400);
}
return $content;
Proposal
My proposal would be to extend CacheManager::get with a Closure as an optional second parameter. This is called the CacheContract Pattern Symfonys implementation
This could look like this:
$cF = GeneralUtility::makeInstance(CacheManager::class)->getCache('identifier');
$content = $cF->get($key,function($key, $cF) use ($var1,$var2) {
// do expensive stuff and write it to $content
$cF->set($key,$content,['tag1','tag2'],86400);
return $content;
});
return $content;
This is a bit different than Symfony does it, but this way the ‘set’ method and the configuration, tag handling, timeout handling could stay the same, making the transition from the old pattern to the new pattern easier.
The get method would simply call the closure - if given - if a cache could not be retrieved, and returning the content as it did before. The changes to the Interface would be minimal and stay backwards compatible.
The old pattern could stay valid in those cases were it could be undesirable to have stale caches (backend?)
Advantages to this approach
There would not be a direct advantage, but once this is implemented the Caching Framework could be enhanced to have a more dynamic approach to cache invalidation and recreation.
If a Cache has timed out the first call to recreate this content could mark the cache as stale. Subsequent calls to the same cache-key would then still deliver the stale cache for a short while, and the first call could take its time to recreate the cached item.
As well cache-clear could mark caches as stale and to-be-recreated rather than expunging them directly, giving the chance for a single recreation.
On Sites with high load and lots of traffic this would have several advantages.
With our current pattern this is impossible to optimize.
Disadvantages
Don’t know? Maybe a CacheGenerator Class implemented by the extension developer would be a better approach. Maybe both could be done…?
It would not be PSR-6, but there has not been much updates, and personally I find this pattern a better solution.
Problems
one would have to check how this can benefit caches created via typoscript and other frontends. My work usually only required the VariableFrontend, so I have not looked at the other Frontends yet.
Next steps
Do others see some benefit here as well? Maybe enough for an Initiative?
I would be willing to spend time and effort and code on this.
An Initiative would of course look into implementing this feature in the core and maybe adapting the cores caches and exploring the optimization of the cache handling as outlined