Skip to content

Commit

Permalink
CRM-20722: 'Lock wait timeout exceeded' error triggered on smart grou…
Browse files Browse the repository at this point in the history
…p cache rebuild

This patch is merged upstream & I am submitting it &
civicrm#10943

to our codebase.

Doing this
a) syncs us with upstream in the area we are working on
b) adds some code consolidation making it easier for us to tinker with the impact of
cache tables.

Note that this change switches from one sql call to many when clearing groups from
the group_contact_cache table. I'm thinking this is probably not a problem for us as we have
not that many groups (& hopefully we can further reduce them).

Also the apparent COMMIT is a bit of a a myth - CRM_Core_Transaction does weird complex
transaction nesting stuff...

Change-Id: I3d6505b04af1134884f660d71316afb2490221d1
  • Loading branch information
monishdeb authored and eileenmcnaughton committed Feb 1, 2018
1 parent ca9aed3 commit 2339807
Showing 1 changed file with 44 additions and 40 deletions.
84 changes: 44 additions & 40 deletions CRM/Contact/BAO/GroupContactCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -300,12 +300,12 @@ public static function updateCacheTime($groupID, $processed) {
* @todo remove last call to this function from outside the class then make function protected,
* enforce groupID as an array & remove non group handling.
*
* @param int $groupID
* @param int $groupIDs
* the groupID to delete cache entries, NULL for all groups.
* @param bool $onceOnly
* run the function exactly once for all groups.
*/
public static function remove($groupID = NULL, $onceOnly = TRUE) {
public static function remove($groupIDs = NULL, $onceOnly = TRUE) {
static $invoked = FALSE;

// typically this needs to happy only once per instance
Expand All @@ -316,21 +316,21 @@ public static function remove($groupID = NULL, $onceOnly = TRUE) {
if (
$onceOnly &&
$invoked &&
$groupID == NULL
$groupIDs == NULL
) {
return;
}

if ($groupID == NULL) {
if ($groupIDs == NULL) {
$invoked = TRUE;
}
elseif (is_array($groupID)) {
foreach ($groupID as $gid) {
elseif (is_array($groupIDs)) {
foreach ($groupIDs as $gid) {
unset(self::$_alreadyLoaded[$gid]);
}
}
elseif ($groupID && array_key_exists($groupID, self::$_alreadyLoaded)) {
unset(self::$_alreadyLoaded[$groupID]);
elseif ($groupIDs && array_key_exists($groupIDs, self::$_alreadyLoaded)) {
unset(self::$_alreadyLoaded[$groupIDs]);
}

$refresh = NULL;
Expand All @@ -340,7 +340,7 @@ public static function remove($groupID = NULL, $onceOnly = TRUE) {
2 => array(self::getRefreshDateTime(), 'String'),
);

if (!isset($groupID)) {
if (!isset($groupIDs)) {
if ($smartGroupCacheTimeout == 0) {
$query = "
DELETE FROM civicrm_group_contact_cache
Expand All @@ -352,7 +352,6 @@ public static function remove($groupID = NULL, $onceOnly = TRUE) {
";
}
else {

$query = "
DELETE gc
FROM civicrm_group_contact_cache gc
Expand All @@ -372,44 +371,49 @@ public static function remove($groupID = NULL, $onceOnly = TRUE) {
AND refresh_date IS NULL
";
}
}
elseif (is_array($groupID)) {
$groupIDs = implode(', ', $groupID);
$query = "
DELETE g
FROM civicrm_group_contact_cache g
WHERE g.group_id IN ( $groupIDs )
";
$update = "
UPDATE civicrm_group g
SET cache_date = null,
refresh_date = null
WHERE id IN ( $groupIDs )
";

CRM_Core_DAO::executeQuery($query, $params);
if ($refresh) {
CRM_Core_DAO::executeQuery($refresh, $params);
}
// also update the cache_date for these groups
CRM_Core_DAO::executeQuery($update, $params);
}
else {
$query = "
DELETE g
FROM civicrm_group_contact_cache g
WHERE g.group_id = %1
";
$update = "
UPDATE civicrm_group g
SET cache_date = null,
refresh_date = null
WHERE id = %1
";
$params = array(1 => array($groupID, 'Integer'));
foreach ((array) $groupIDs as $groupID) {
self::clearGroupContactCache($groupID);
}
}
}

CRM_Core_DAO::executeQuery($query, $params);
/**
* Function to clear group contact cache and reset the corresponding
* group's cache and refresh date
*
* @param int $groupID
*
*/
public static function clearGroupContactCache($groupID) {
$transaction = new CRM_Core_Transaction();
$query = "
DELETE g
FROM civicrm_group_contact_cache g
WHERE g.group_id = %1 ";

if ($refresh) {
CRM_Core_DAO::executeQuery($refresh, $params);
}
$update = "
UPDATE civicrm_group g
SET cache_date = null, refresh_date = null
WHERE id = %1 ";

$params = array(
1 => array($groupID, 'Integer'),
);

CRM_Core_DAO::executeQuery($query, $params);
// also update the cache_date for these groups
CRM_Core_DAO::executeQuery($update, $params);

$transaction->commit();
}

/**
Expand Down

0 comments on commit 2339807

Please sign in to comment.