This is a follow-up from #1208562: Avoid variable_set() in rules_get_rule_set(). I noticed the variable_set() is still getting called very often, had a look through places it gets updated, and this looks like a likely candidate:
/**
* Implements hook_flush_caches().
*/
function rules_flush_caches() {
variable_del('rules_empty_sets');
return array('cache_rules');
}
If you have cron running every five minutes or so, then the site will almost constantly be building the variable before its destroyed again.
Possible things to do:
1. Move it to a permanent cache item. This means an extra cache_get() compared to stuffing it in variables, but then there'd be no need to separately handle clearing it.
2. Add some rate limiting (could use another variable, or core's flood control), but that'd mean it might not get cleared when there's a genuine cache clear during development.
I started looking at #1, but rules is currently using global $conf value directly with a note to say this is to avoid a static cache. I think in this case it's probably going to be better to add the cache, but it might need some thought.
| Comment | File | Size | Author |
|---|---|---|---|
| #16 | d7_rules_cache.patch | 5.47 KB | fago |
| #14 | d7_rules_cache.patch | 4.69 KB | fago |
| #10 | rules-convert_empty_sets_variable_to_cache-1555634-10.patch | 4.88 KB | pdrake |
| #9 | rules-convert_empty_sets_variable_to_cache-1555634-9.patch | 4.88 KB | pdrake |
| #4 | rules_variable_set_D6_2.patch | 3.16 KB | catch |
Comments
Comment #2
catchOK here's patches for D6 and D7. Only cursory testing so far.
Comment #3
catchMissed a bit in the D6 patch - was still initializing from the old variable.
Comment #4
catchOne more revision to the D6 patch, with this change we can actually revert the other issue as far as I can tell, the problem was the variable being cleared in the first place, not that identical variables were being set. D7 patch is still good I think, although I don't have a real D7 site with rules installed to test on.
Comment #5
catchThis is now running in production on a D6 site fwiw.
Comment #6
unitedwallabies commentedI was about to file a bug of my own on this subject. It does not seem right, that Rules-module uses the
variable-table as its own cache...We replicate the master-database to (a lot of) slaves using local memcache on each slave for their own private caching — to avoid database traffic. The incessant insertions/deletes from the master database cause us grief. If the
rules_empty_setsis, indeed, a variable, then it should not be deleted each time a cache-clear is performed. And if it is a cache-item, then the value needs to live where the rest of the cache does (either in the default bin or in a bin of its own).We'll try to use the proposed patch (for D7)... Thanks!
Comment #7
unitedwallabies commentedIn reply to #2
Thank you very much for offering the patches. I have a question, however, about it. Instead of storing the value of
rules_empty_setsin thevariable-table, you place it in the cache (in the newcache_rulesbin). But don't you need to explicitly clear the bin, when a cache-flush is requested?And if it is not necessary, perhaps the entire
rules_flush_cacheshook can be eliminated?If this is, indeed, the only thing in the new
cache_rulesbin, maybe, using the defaultcachebin is better?Comment #8
mitchell commentedI only did a quick test of applying the patch, clearing the cache, and running a rule. There were no apparent side effects of applying this patch.
Comment #9
pdrake commentedHere's a bit of a re-roll of this patch, addressing some additional areas where the variable was being used.
Comment #10
pdrake commentedThis patch should work better.
Comment #11
pdrake commentedHere's an interdiff of the last two patches:
interdiff rules-convert_empty_sets_variable_to_cache-1555634-9.patch rules-convert_empty_sets_variable_to_cache-1555634-10.patch
diff -u b/rules.module b/rules.module
Comment #12
berdirA different example where rebuild is still triggered on every request (!) is when you render exportable/configuration entities.
The reason for this is that the default rules event controller is not added for this, but the view event is still called by EntityAPIController. Because that event does not exist, it is not in empty set, nor is there a cache entry for it. Which results in a rules event rebuild on every request where such an entity is viewed.
That is, in my case, every page ;)
I'm not sure why rules explicitly keeps track of empty sets, instead of simply tracking which sets actually have rules in them?
Comment #13
fagoYep, but the problem here is modules invoking events that do not exist I think. I don't think we should optimize for that, but rather fix that.
I agree that would make most sense, not sure why we started it the other way round. I think the thought was to not duplicate existing cache information, but we are doing that anyway (regardless of inversion).
Also, keeping track of existing items would help with #1993932: Add support for event settings, where the negated approach cannot be used any more.
Comment #14
fagook, attached patch moves to an whitelist and removes the variable_del() during cron run. I think it's unnecessary as it should be enough to update the variable when caches are already rebuilt anyway or a reaction rule got configured.
Patch attached.
Comment #16
fago#1993932: Add support for event settings got committed, what means we really need to do this now. Re-rolled patch -> let the bot run.
Comment #17
fagoCommitted.
Comment #19
fabianx commentedThis totally was the wrong fix.
The problem was using variable_get/_set in the first place not deleting it at cron or moving to a white list.
#2190775: Misuse of variables table with rules_event_whitelist is the follow-up. Please please please get this in.
Thanks!