Hello,
Cache backend management is a low-level critical functionallity, doing the Cache Backport module, I also added some code improvements into the D6 backport.
I think Drupal 7 could benefit those improvements, since they are API compatible and could avoid some crashes on misconfigured environments.
Basically, I do all of this:
- Adding an interface for strongly environment related backends, backends that needs external libraries to run steamlessly should implement a new
checkEnv()method in order for core to test if the environment if ready. - I added a dummy implementation of this method on the database backend, as a code sample.
- I added a
class_exists()call at cache backend instanciation time, if the current class does not exists, the backend gracefully downgrade to default. - Added the necessary
checkEnv()calls while instanciating the backend class, and provide a graceful downgrade to default if it fails. - Added a bonus Null Object implementation of cache backend; this allows site administrators or developers to disable fully cache for one or more bins by configuration.
Using this interface improvements, it can be easy to implement administration screens (at least report screen) for various cache backends state, what I did in the D6 backport, and I could easily do for D7 if people are interested.
Cache backend being plugins is now being discussed for D8, so that's why I won't do a D8 patch until the solution to this problem comes up, until, this can still provide a nice consistency bugfix for D7 next release.
Comments
Comment #1
pounardThis makes the system more robust at the cost of less than (number of bins) * function calls. I needed it while I was iterating on development phases on some custom projects, and this code has proven to me to be working quite well. Well, on the D6 cache backport module it did, but this patch is basically almost the same code, with better Drupal code convention support and better documentation. I tested some use cases on a D7 instance even run some UNIT tests (well, not every of them because my box is dawn slow).
Comment #2
damien tournoud commentedFeature requests needs to go to D8 first, nonetheless.
About the patch:
* We try not to abbreviate, checkEnv() should be named checkEnvironment(), or most preferably something like
isHealthy()because there could be more reasons for a cache not to be available then just missing libraries* We already have a Null cache (DrupalFakeCache)
Comment #3
damien tournoud commentedAlso, the final hardcoding of DrupalDatabaseCahe feels weird to me:
A better strategy would be to try the default cache implementation first, and if it fails fallback to the fake cache.
Comment #4
pounard@#2
Sounds right for the method naming. Doesn't really care about the name as soon as it express the purpose.
Didn't see the DrupalFakeCache, probably should it live in the cache.inc, I mean, is the cache-install.inc loaded on normal runtime?
@#3
I'll provide a clearer patch.
Since a misconfigured settings.php file can lead to WSOD with the actual cache.inc, I'm switching this down to bugfix, not feature request anymore.
Comment #5
pounardDrupalFakeCache embeds specific code for install time (messes up with Database) what a real Dummy/Stumb/Null/Neutral object should not, maybe should it be renamed to DrupalInstallCache instead, and DrupalFakeCache should be my own implementation? Plus, a real Null Object implementation shouldn't rely on a base class that's a totally messed-up and broken design.
Comment #6
damien tournoud commentedI'm pretty sure it was named DrupalInstallCache at one point. We should try to track down where it changed. Agreed on the broken design, but it makes sense at install time.
Comment #7
pounardYes, I'm rewriting the patch.
Comment #8
pounardOk, here is a more complicated patch, implementing Damien suggestions:
DrupalFakeCacheasDrupalInstallCache, which should probably be better for code comprehension.DrupalInstallCache.DrupalFakeCacheis now defined in thecache.incwhich makes more sense since it can be used voluntarely by site admins or developers to do testing. It is now a real Null Object implementation that does not extends theDrupalDatabaseCacheanymore._cache_get_object()with more checks. Default backend class is statically cached, if it fails once, the system downgrades to the null implementation instead. This means that misconfigured sites will suffer from performance problems, but won't WSOD anymore.checkEnv()method asisHealthy()as Damien suggested (it makes sense to me).There are a few things to consider here, but I think this patch can work as-is without going further, nevertheless:
DrupalInstallCacheis an insane and unnecessary code indirection, and should be definitely removed as theinstall-cache.incfile. It should use the real null implementation aKaDrupalFakeCacheinstead.EDIT: Fixed some typo errors.
Comment #9
pounardSwitching to needs review.
Comment #10
catchThere is an existing issue for a null cache backend at #1082328: Provide a proper no-op cache.inc, although no patch.
DrupalInstallCache is necessary due to ajax requests to the Drupal site during install (I think this is the clean URL check, not sure what else), it is a hack, but it can't be removed without dealing with the bugs it works around.
Why not put the health check in the catch section of a try/catch block? If get() returns something valid and no error then it is already healthy. #1167144: Make cache backends responsible for their own storage contains some discussion around this.
Comment #11
pounardWe related all of that, and my implementation actually keeps the installation backend, but renaming it, while it created a real fake implementation into a simpler version which is actually a real null object pattern implementation (that get the name of the older one, therefore keeping backward compatibility).
The try/catch implementation is not likely to be useful here because we cannot catch while instanciating based on the get() errors.
My whole patch is about not ending up with a WSOD (which with the actual code can happen) and keeping full API compatibility. It adds some new stuff but there are basically dormant if you don't use it and doesn't modify the actual API.
Comment #12
pounardHello, waking up this issue since I'm actually developing cache backend, it's the right time for me to have a final answer about this issue.
@Damien Tournoud you made pertinent comments, now that I fulfilled every one of them, should be the right time for a go or a no go.
@catch I think this issue is not incompatible with the others being opened, and the isHealthy() method could be the right one were to implement the lazy table creation (or anything else depending on the backend).
Comment #13
damien tournoud commentedRe-filling properly.
This should be easily backportable, but I suggest we fix the name of the interface and the documentation:
There is no such thing as a "Plugin" in Drupal at this stage. This is not meant to be a generic implementation of a "strongly environment related plugin". This is just meant as a way for a cache implementation to declare if it is healthy or not.
If down the road we want to tackle the generic problem, we will. In the meantime I don't see this getting in without making it specific to the cache system.
Comment #14
pounardOk, I don't see any problems with that suggestion, let me redo the patch and we could then discuss it further.
EDIT: But I really don't see why loosing the generic aspect, when we look at this issue: #402896: Introduce DrupalCacheArray and use it for drupal_get_schema() the proposition is meant to give a generic solution (and a good candidate for backport) for potential modules or other core usage.
Maybe the terminology indeed can be changed, the plugin word can be confusing; But the generic aspect, even if not being used right now, is still a potential future benefit.
Comment #15
pounardNew patch attached, did on latest 7.x, should pass on 8.x as well.
Changes:
Comment #16
pounardForgot the patch..
Comment #17
pounardComment #19
pounardComment #20
dtwork commented#16: drupal-7.x-git-cache_backend_env_downgrade-3.patch queued for re-testing.
Comment #21
pounardWrong tab, forget it.
Comment #22
pounardComment #23
Anonymous (not verified) commentedsubscribe.
Comment #24
pounardAttached patch following latest commit from catch API modifications.
Comment #25
pounardThis still includes the FakeCache correct implementation, sorry if it mixes up with the other related issue, but it's simpler this way.
Comment #26
pounardPersonal reminder: need to separate the null object cache implementation and put in the right issue: #1082328: Provide a proper no-op cache.incDone, and waiting for it to be commited to fix the patch here.
Comment #27
thedavidmeister commented#24: drupal-8.x-git-cache_backend_env_downgrade-4.patch queued for re-testing.
Comment #42
smustgrave commentedThank you for sharing your idea for improving Drupal.
We are working to decide if this proposal meets the Criteria for evaluating proposed changes. There hasn't been any discussion here for over 8 years which suggests that this has either been implemented or there is no community support. Your thoughts on this will allow a decision to be made.
Since we need more information to move forward with this issue, the status is now Postponed (maintainer needs more info). If we don't receive additional information to help with the issue, it may be closed after three months.
Thanks!
Comment #43
smustgrave commentedSince there's been no follow up in 3 months going to close out, but don't worry if still valid it can be reopened. Thanks all!