I have written a new D6 module called "Dynamic Cache" which allows other modules to disable Drupal's standard caching from hook_boot(), for any arbitrary runtime conditions.
Due to the execution sequence of Drupal's bootstrap system, it is not normally possible to disable standard page caching from hook_boot(), because the cached page is already loaded before hook_boot() is invoked.
Page caching can be disabled on a per-page basis easily enough though programmatic methods, or the cacheexclude module. However there is no way of disabling the cache on a per-user basis (ie, disable cache for a given page, for some anonymous users but not others), except for manipulating global variables in settings.php.
You can see a discussion about this issue here: http://drupal.org/node/322104. It has not been resolved, even for D7, much less D6.
We have found a way to bypass this limitation, by essentially "hijacking" (ie, not returning to) Drupal's normal bootstrap process, and completing the rest of it ourselves. This is actually much simpler than it sounds, and works perfectly.
We have been using this technique without issue (in fact it immediately solved all of our caching issues) on a busy, live production site for some time now, and I would now like to contribute it to the community. I believe it to be a simple, original, and ingenious solution to a limitation of Drupal's standard caching mechanism, with extremely wide applicability. Hopefully this same method will also work for D7, however that is not something I have examined at this time.
I posted preliminary details on this technique in the forums (http://drupal.org/node/875152), but have now taken the time to turn it into a standalone module. I have done my best to follow Drupal's coding conventions, wrote a detailed README.txt, and implemented an install hook to ensure a very high module weight, since Dynamic Cache's hook_boot() must run after any other module's hook_boot().
I have been involved in the Drupal community in some form or another for over four years (often providing help on forums and issue queues) and have built dozens of sites from very small to very large. I recently attended DrupalCon Copenhagen where I had the great pleasure of meeting Dries, webchick, and many others, and found myself inspired and encouraged to contribute more actively back to the community. I was a presenter at DrupalCamp Alberta 2010 last weekend, and will be attending the Pacific Northwest Drupal Summit in a couple weeks.
- Sandbox: http://drupal.org/sandbox/brian_c/1413374
- Git repo: http://git.drupal.org/sandbox/brian_c/1413374.git (PAReview)
- Drupal core version: 6.x
| Comment | File | Size | Author |
|---|---|---|---|
| #1 | dynamic_cache.zip | 3.01 KB | brian_c |
Comments
Comment #1
brian_c commentedModule attached.
Comment #2
avpadernoHello, and thank you for applying for a CVS account. I am adding the review tags, and some volunteers will review the code, pointing out what it needs to be changed.
What is used as code for the proposed module could be used to create a custom index.php that would replace (for sites that needs it) the default index.php file Drupal comes with.
Comment #3
brian_c commentedI don't believe this functionality can be achieved with a modified index.php, it would need to change bootstrap.inc. This module effectively bypasses the part of bootstrap.inc that would display a cached page, invokes the remaining bootstrap phases, then completes the remaining (unchanged) steps from index.php.
Modifying bootstrap.inc to accomplish this, is the exact subject of this thread: http://drupal.org/node/322104, but after two years it has still not been resolved, for D6 or for D7.
Given that, isn't it better to provide a module that can accomplish this immediately using the existing hook system (albeit in a novel way), instead of modifying core?
Thanks very much for your time.
Comment #4
avpadernoComment #5
brian_c commentedAnything I can do to help move this along?
Have been using this code with zero issues on a large production site for 5+ months now.
I know at least one other person who is successfully using this module as well, they wrote about it here: http://gristmillmedia.wordpress.com/2011/01/14/drupal-conditional-page-c...
One thing I am not 100% sure about, is whether the module always assigns itself a high weight properly (to ensure its hook_boot() executes last). I copied what the Devel module does, just updating the system table manually via hook_install(), but am not sure it works all the time; I think I've seen the module weight remain unchanged (0) after install in some cases.
Comment #6
TimMachine commentedYes, it's working well for us right now on two sites in which we need to be able to display pages that shouldn't be cached to specific anonymous users.
We implemented it last week and so far haven't seen any problems.
Thanks Brian!
Comment #7
avpadernoI will report here a little checklist:
Comment #8
zzolo commentedHi. Please read all the following and the links provided as this is very important information about your CVS Application:
Drupal.org has moved from CVS to Git! This is a very significant change for the Drupal community and for your application. Please read the following documentation on how this affects and benefits you and the application process:
Migrating from CVS Applications to (Git) Full Project Applications
Comment #9
djdevinRebooting an old thread. This module saved us several times, for example when trying to detecting incoming SSO via cookies, logged out as an anonymous user. Any more work on this? Would love to see a project page.
Comment #10
brian_c commentedHiya, glad you are finding the (proto) module to be useful!
No real updates... I kinda stopped pursuing this when the whole CVS -> Git switchover happened. Now that the dust has settled on that I should probably try again to make this into an actual project. Looks like I need to set it up as an "Experimental Project" with the new system. Will see if I can find some time in the next week or two.
Comment #11
djdevinWould you mind if I create the project page? I have Git access with several other projects, and can clean up the module. Not sure how much future development it would need, but I could of course make you a co maintainer.
Comment #12
brian_c commentedLemme give it a shot myself first, if you don't mind. I will try this week.
Comment #13
onelittleant commentedBump.
This module does what it does very nicely. We use it on a site where depending on a particular session variable we want anonymous users to skip the cache. Prior to this module, we had to disable caching site-wide. Now our average response times are cut in half or less for anonymous users!
I'd like to see it available to the community. Let me know if you want assistance rolling this into a project.
Comment #14
gregglesPlease see http://drupal.org/node/916552#comment-4147170 for how to move this forward.
Comment #15
doublejosh commentedbrian_c do you just need to create a sandbox?
Comment #16
brian_c commentedI have (finally) created a sandbox for this project here: http://drupal.org/sandbox/brian_c/1413374
I am not sure whether I should be applying for Full Project status right away, or leave it as a sandbox for a while?
Comment #17
avpadernoI am moving the issue to the right queue.
Comment #18
misc commentedHi,
The project is to small to get full project access:
But you could apply just to get this project out as an full project. You could read more in this discussion: http://groups.drupal.org/node/195848
I did an automatic code review: http://ventral.org/pareview/httpgitdrupalorgsandboxbrianc1413374git - there some issues to take care about. Please feel free to ask if you have any questions.
Comment #19
doublejosh commentedNot sure what this could be combined into, but I use it on production to get around logging in SSO users.
My colleague borrowed this code to create a UserAgent cache bypass. Perhaps this module could be a generalized Cache ByPass module with a few components/uses.
Comment #20
patrickd commentedComment #21
misc commentedYou don't need to combine this module with existing ones, but you could not get full git access to create projects with a small module as an application, but you could try to have this promoted to a single project on a drupal.org.
Comment #22
brian_c commentedYes I'd like to get this promoted as a single module then... don't really care if I have "promote at will" rights (didn't even know I was applying for that?), nor do I intend to bloat this to 120 lines / 5 functions when it's not needed.
I need to find time to go through the latest coding requirements I'm apparently no longer satisfying first.
Comment #23
nevosa commentedHi Brian,
I'm using this code in a large production already, and it works very nicely.
I've also created a sandbox project called "anonymous theme" that uses this code and would be very happy to see it published!
see:
http://drupal.org/sandbox/nevos/1507962
Comment #24
doublejosh commentedBTW: Here is the output of the Coding Standards sniffer...
Comment #25
rjacobs commentedThough the code is very short and simple, it seems that having this available as a proper module/project makes good sense. This would allow other module developers that depend on this functionality to simply define a dependency instead of incorporating their own (possibly inconsistent or hacky) methods of conditionally disabling the cache. Having this as a project would also provide a "go-to" place for exploring this concept in D7. Perhaps this could even grow into a module that manages a wide-range of simple, yet low-level, cache controls.
I suppose there are few issues in the sandbox queue that might warrant attention before moving too far forward with all this. At the moment there are 2 bug reports (I just added one, but I think it has a very easy solution):
http://drupal.org/project/issues/1413374
Comment #26
doublejosh commentedFYI: I'm involved in a D7 upgrade that will require this module. #1515474: D7 version
Likely I'll add a patch there.
Comment #27
rjacobs commentedIt's looking like there is certainly some demand for getting this functionality out there as a full project, and as I noted above, this is the kind of thing that other modules could nicely leverage as a dependency.
Given that this has been an open case for quite some time, I'd like to offer whatever help I can to get this module to full project status while also staying in-line with brian_c's intentions. For example, I would be willing to:
Of course if brian_c wants to keep moving this through as an app for individual project git access, or grow the module to the point where this can be an app for full git access, that's all good. I just wanted to suggest an alternative that might accomplish the same objectives a bit faster.
Comment #28
iamEAP commentedAs a user of dynamic_cache and maintainer of UA Cache Bypass, I'm on board with rjacobs in #27. Perhaps someone could reach out to brian_c?
Comment #29
brian_c commentedHi guys, I have been following this but have been too swamped at work with multiple converging site launches to put any time towards it recently. I am wrapping some things up this week, taking a much-needed vacation at the end of the week (weekend in Vegas baby), then should have time to dig back in when I get back. I want to correct the code sniffer stuff and re-submit.
I wanted to get this submitted as my own project, to better motivate myself to maintain it (and make myself more familiar with the Git workflow), as part of "getting my feet wet" at helping contribute more back to the community than just the odd forum/issue post.
Comment #30
rjacobs commentedHi Brian,
The decision is totally yours! My guess is that if you are willing to run-through at least points 3 and 4 from comment in #27 within your sandbox, and if no other issues crop-up, this application can probably be marked as "reviewed". After that it would be a matter of seeing how long it would take for one of the folks with git admin access to see this, give it a final review, and then hopefully decide to grant project-specific access to you. My understanding is that the number of people with git admin access (the ability to setup git access that is not associated with an existing project) is very small, so I think getting their attention is the tricky part. Someone please correct me if I am wrong in this summary.
Having someone who already has git access start the project and give you co-maintainer access could essentially lead to the same result (you would be a project maintainer, with the same rights as any other maintainer). It just requires someone who's willing to personally help out and kick-start things for you, and you can see there are a couple such people out there.
My personal feeling is that if you are willing to see it through the whole way yourself you'll probably learn more about the process and community, and we'll all benefit from that. So I think that's a great approach. I just wanted to somewhat 'bump' the issue by offering my own help.
Looking forward to reviewing your sandbox updates!
Comment #31
brian_c commentedAlright, fresh bunch of commits, ready for re-review.
Notes:
- Created branch "6.x-1.0-rc1"
- Have updated code to comply with Coder & CodeSniffer
- Have included patch from the 1 bug on the issue queue: #1425156: Dynamic_cache should be bypassed in certain admin contexts (drush, cron, etc.).
- Have also written a testing module for Dynamic Cache, which provides a simple test page
The test module now puts the code at well over 120 lines and 5 functions, if that matters.
Here is the automatic code review: http://ventral.org/pareview/httpgitdrupalorgsandboxbrianc1413374git-6x-1...
Comment #32
rjacobs commentedThanks Brian,
A few comments. These are mostly minor points, and I don't think they are deal-breakers to getting dynamic_cache set as an official project, but I think responding to some of these points might make it more likely that you could leverage this git application for proper git access, as opposed to just single-project git access:
Thanks for posting your changes.
Comment #33
brian_c commentedThanks for the reply. On your points:
Appreciate the tips and suggestions, thanks.
Comment #34
brian_c commentedActually, on further reflection, it occurs to me that high-performance sites may attempt to disable Drupal's automatic session creation for anonymous users (ie, as discussed here: http://drupal.org/node/183006), so I do think cookies are probably the most robust option.
Comment #35
brian_c commentedI see your point about how the cookie could disable the cache site-wide within the same browser session though, I've modified the check so that the the test cookie now only affects the test page.
I have also committed new "6.x-1.x" branch.
Comment #36
brian_c commentedUpdated code review link for 6.x-1.x branch: http://ventral.org/pareview/httpgitdrupalorgsandboxbrianc1413374git-6x-1x
Comment #37
rjacobs commentedGreat, thanks for the replies,
I think the bottom line is that you have given great consideration to performance and scalability in this effort (certainly more so than I in a review capacity), plus you have a good sense of Drupal structures and APIs and appear to be leveraging the community in your efforts. In my option that should speak even louder than whether or not you meet some hard limit on the amount of code included with the application (you probably meet that limit now anyway if counting the test logic). I personally don't see any reason why this can't be a full git access application.
You have also addressed some of the "housekeeping" issues (coder, readme, etc). The only exception might be choosing which "package" to assign in the .info, but hey, I don't think that needs to stand in the way of promoting this effort.
So I'd like to just mark this as reviewed. We know several others have tested the core logic behind this module (and are using it in production), so review attention has been thorough.
Some more specific replies appear below:
------------
Regarding the extra module, this probably is a fine case where having tests in a separate contained module makes sense. I don't know the true relative cost of an extra "if" check in hook_boot, but your justification makes me agree that it should be avoided.
In terms of the cookie vs query, etc. A query parameter could toggle the logic of the test, but you are correct in that it could lead to different cache results for a given page request. Anyway, having the extra check to confirm you are on the test page while checking the cookie really resolves things (the issues was pretty nominal anyway).
Also in terms of tests, if you are willing to explore the usage of a block to report test results I think that would really be the best case (but my vote is to save that effort until this app process is complete so we can get this thing out there).
For the package assignment, how about "Performance and scalability" (I think this is one of the best practice suggested examples). Really, this module is all about performance, as it's a way for people to generally keep caching enabled while still having a way to conditionally bypass it.
Lastly, regarding the git branching and tagging, I don't think there are any "rules" about how you assign branch names for your own working purposes, but when it comes time to make public releases several Drupal systems depend on certain naming conventions (http://drupal.org/node/1015226 explains it all best). All this is surely something you would have sorted out on your own (when setting up a release after getting this promoted), but I figured it was worth pointing out now.
Thanks!
Comment #38
iamEAP commentedI'll echo rjacobs on the package assignment "Performance and scalability" is probably the way to go.
Otherwise, count this as a +1 to RTBC, particularly echoing rjacobs' sentiments on leveraging community, and the use of this module in production environments.
Comment #39
brian_c commentedThanks guys.
Comment #40
brian_c commentedPackage has been switched to "Performance and scalability"
Comment #41
klausimanual review:
But that are just minor issues, so ...
Thanks for your contribution, brian_c! Welcome to the community of project contributors on drupal.org.
I've granted you the git vetted user role which will let you promote this to a full project and also create new projects as either sandbox or "full" projects depending on which you feel is best.
Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.
As you continue to work on your module, keep in mind: Commit messages - providing history and credit and Release naming conventions.
Thanks to the dedicated reviewer(s) as well.
Comment #42
brian_c commentedThanks all.
Full project page is now up (with an RC1 release):
http://drupal.org/project/dynamic_cache
Comment #42.0
brian_c commentedUpdated issue summary.
Comment #43
avpaderno