-
-
Notifications
You must be signed in to change notification settings - Fork 825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
flushCaches should respect permitCacheFlushMode. Also flush caches which have a NULL cache_date #21430
Conversation
(Standard links)
|
So I feel like we have some shifting goal posts over what a cache date of NULL means. I guess it probably originally meant
But along the way we started setting NULL to indicate 'should be rebuilt' and it stopped being a given that it would already be cleared out. So, I think this is correct in our evolution of this code. However, I think this could cause extra queries - which you are trying to avoid Say we have 100 groups and 50 of them are never used. Every time this function is called those 50 will be NULL - so even if no groups are out of date and we are not about to build on of the unused groups they will be found by the query and Maybe handling expired & null separately makes sense with a check first eg
|
Hmm further thought - maybe the part above that matters is the 'do a quick get to see if any rows need to be deleted before doing a potentially locking query on the group contact cache. ie that could be done regardless of how the group is invalidated. In general the problem is too many locking queries - an extra get with LIMIT = 1 is not expensive. |
if (!CRM_Core_Config::isPermitCacheFlushMode()) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eileenmcnaughton Do you think this bit is ok as-is? If so I'll split it off into it's own PR and work through the more complex bits separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mattwire yeah I think it is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok see #21468
e79d595
to
8d8959e
Compare
$groupsToFlushSQL = 'SELECT group_id FROM civicrm_group_contact_cache gc INNER JOIN civicrm_group g | ||
WHERE cache_date <= %1 OR cache_date IS NULL GROUP BY group_id'; | ||
$groupsDAO = CRM_Core_DAO::executeQuery($groupsToFlushSQL, $params); | ||
$expiredGroups = []; | ||
while ($groupsDAO->fetch()) { | ||
$expiredGroups[] = $groupsDAO->id; | ||
$expiredGroups[] = $groupsDAO->group_id; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eileenmcnaughton Alternative based on your suggestion. This only runs the delete query if there is actually data to be cleared out. This also prevents a DELETE being run when cache_date was set but expired and the group had no records (or was already cleared somehow!).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mattwire my suspicion is that inclusing the civicrm_group_contact_cache
in the query will mean it potentially returns thousands and thousands or results. I think 2 quick queries (1 to get the groups & 1 to check if there is at least one row to delete) will be quicker than 1 slow one
fe5ca48
to
c34f9a0
Compare
@eileenmcnaughton Ok, here's an alternative. 2 quick select queries followed by the DELETE/UPDATE only if necessary. |
$params = [1 => [self::getCacheInvalidDateTime(), 'String']]; | ||
$groupsDAO = CRM_Core_DAO::executeQuery("SELECT id FROM civicrm_group WHERE cache_date <= %1", $params); | ||
$groupsThatMayNeedToBeFlushedSQL = 'SELECT id FROM civicrm_group WHERE saved_search_id IS NOT NULL AND (cache_date <= %1 OR cache_date IS NULL)'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs to be (saved_search_id IS NOT NULL OR children <> '')
I'm not sure if children would be NULL or an empty string but <> ''
should get both
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated!
test fail unrelated test this please |
@mattwire this seems right with the one change to also include 'children' |
…ich have a NULL cache_date
33c81f6
to
ff85b03
Compare
OK - I think this is good now. |
Overview
Found via experimental #21384.
There is an option to prevent cache flushes
CRM_Core_Config::isPermitCacheFlushMode()
(currently only used by the importer) but it's only respected if we flush caches via theCRM_Contact_BAO_Contact_Utils::clearContactCaches()
function which is bypassed by both opportunistic and deterministic (group contact) cache flushes. This means it's quite likely caches will be flushed anyway probably triggering deadlocks.A group contact cache can have a NULL cache date if (1) it's never been built, (2) it's been invalidated but not flushed. But
flushCaches()
will only clear cache entries for groups which have an expired cache date.Before
Group contact cache flushed even if
CRM_Core_Config::isPermitCacheFlushMode()
returns FALSE when opportunistic/deterministic cache flush is triggered.Group contact cache not cleared if it has a NULL cache date.
After
Group contact cache not flushed if
CRM_Core_Config::isPermitCacheFlushMode()
returns FALSE when opportunistic/deterministic cache flush is triggered.Group contact cache cleared if it has an expired or NULL cache date.
Technical Details
#21384 fails cache tests because the tests are testing things in a very specific way which is not necessarily how the cache should work. Looking into improving those tests identified the two issues in this PR which make fixing those tests much easier and should make the group contact cache more consistent as well as reduce deadlocks (during import at least).
Comments
@eileenmcnaughton