Improve sync efficiency on memory

This commit is contained in:
Rich Lott / Artful Robot 2024-02-28 14:45:20 +00:00
parent 0b96026602
commit 61a912e2a5
2 changed files with 33 additions and 12 deletions

View file

@ -18,6 +18,8 @@ use CRM_Core_DAO;
class Sync extends \Civi\Api4\Generic\AbstractAction { class Sync extends \Civi\Api4\Generic\AbstractAction {
public function _run(Result $result) { public function _run(Result $result) {
ini_set('memory_limit', '512M');
Civi::log()->debug('Begin', ['=start' => 'ContactCatSync', '=timed' => 1]);
$settings = Civi::settings()->get('contact_categories'); $settings = Civi::settings()->get('contact_categories');
$settings = Setting::get(FALSE) $settings = Setting::get(FALSE)
->addSelect('contact_categories') ->addSelect('contact_categories')
@ -47,17 +49,21 @@ class Sync extends \Civi\Api4\Generic\AbstractAction {
} }
} }
if ($smartGroups) { if ($smartGroups) {
Civi::log()->debug('Refreshing smart groups', ['=' => 'timed', 'groups' => $smartGroups]);
\CRM_Contact_BAO_GroupContactCache::loadAll($smartGroups); \CRM_Contact_BAO_GroupContactCache::loadAll($smartGroups);
Civi::log()->debug('', ['=' => 'pop']);
} }
Civi::log()->debug('Resetting table', ['=' => 'timed']);
// clear out temp space. // clear out temp space.
CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category SET next_category = 0;"); CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category SET next_category = 0;")->free();
// ensure we have all our contacts covered. // ensure we have all our contacts covered.
CRM_Core_DAO::executeQuery(<<<SQL CRM_Core_DAO::executeQuery(<<<SQL
INSERT IGNORE INTO civicrm_contact_category INSERT IGNORE INTO civicrm_contact_category
SELECT id, 0 as category, 0 next_category SELECT id, 0 as category, 0 next_category
FROM civicrm_contact FROM civicrm_contact
SQL); SQL)->free();
Civi::log()->debug('', ['=' => 'pop']);
foreach ($settings['groupIDs'] as $groupID) { foreach ($settings['groupIDs'] as $groupID) {
if ($groupID == 0) { if ($groupID == 0) {
@ -70,6 +76,7 @@ class Sync extends \Civi\Api4\Generic\AbstractAction {
continue; continue;
} }
$isSmart = !empty($groups[$groupID]['saved_search_id']); $isSmart = !empty($groups[$groupID]['saved_search_id']);
Civi::log()->debug($groups[$groupID]['title'], ['=' => 'timed', '=start' => "group$groupID"] + compact('isSmart'));
if (!$isSmart) { if (!$isSmart) {
$sql = <<<SQL $sql = <<<SQL
UPDATE civicrm_contact_category cc UPDATE civicrm_contact_category cc
@ -87,8 +94,10 @@ class Sync extends \Civi\Api4\Generic\AbstractAction {
WHERE next_category = 0 WHERE next_category = 0
SQL; SQL;
} }
CRM_Core_DAO::executeQuery($sql); CRM_Core_DAO::executeQuery($sql)->free();
Civi::log()->debug('', ['=' => 'pop']);
} }
Civi::log()->debug("Calculate changes", ['=' => 'timed', '=start' => "changes"]);
$changes = CRM_Core_DAO::executeQuery(<<<SQL $changes = CRM_Core_DAO::executeQuery(<<<SQL
SELECT id, category, next_category SELECT id, category, next_category
FROM civicrm_contact_category FROM civicrm_contact_category
@ -102,14 +111,23 @@ class Sync extends \Civi\Api4\Generic\AbstractAction {
if (empty($batch)) { if (empty($batch)) {
return; return;
} }
$newCategoryId = (int) ($lastChange[1] ?? 0);
// Create activity // Create activity
Activity::create(FALSE) $a = Activity::create(FALSE)
->addValue('target_contact_id', $batch) ->addValue('target_contact_id', $batch[0])
->addValue('activity_type_id:name', 'changed_contact_category') ->addValue('activity_type_id:name', 'changed_contact_category')
->addValue('source_contact_id', \CRM_Core_BAO_Domain::getDomain()->contact_id) ->addValue('source_contact_id', \CRM_Core_BAO_Domain::getDomain()->contact_id)
->addValue('status_id:name', 'Completed') ->addValue('status_id:name', 'Completed')
->addValue('subject', $catNames[$lastChange[0] ?? 0] . ' → ' . $catNames[$lastChange[0] ?? 0]) ->addValue('subject', $catNames[$lastChange[0] ?? 0] . ' → ' . $catNames[$newCategoryId])
->execute(); ->execute()->first();
$activityID = (int) $a['id'];
// Join activity to all relevant contacts
CRM_Core_DAO::executeQuery("INSERT INTO civicrm_activity_contact (contact_id, activity_id)
SELECT id contact_id, $activityID activity_id
FROM civicrm_contact_category cc
WHERE cc.next_category = $newCategoryId
")->free();
Civi::log()->debug(count($batch) . " changes: " . $catNames[$lastChange[0] ?? 0] . ' → ' . $catNames[$lastChange[1] ?? 0]);
}; };
while ($changes->fetch()) { while ($changes->fetch()) {
$n++; $n++;
@ -120,13 +138,19 @@ class Sync extends \Civi\Api4\Generic\AbstractAction {
} }
$batch[] = $changes->id; $batch[] = $changes->id;
} }
$changes->free();
$writeBatch(); $writeBatch();
Civi::log()->debug('Apply changes', ['=change' => 'applyChanges', '=timed' => 1]);
CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category
SET category = next_category WHERE category <> next_category"); SET category = next_category WHERE category <> next_category")->free();
Civi::log()->debug('', ['=pop' => 1]);
$summary = CRM_Core_DAO::executeQuery("SELECT next_category, count(*) from civicrm_contact_category group by next_category")->fetchAll(); $summary = CRM_Core_DAO::executeQuery("SELECT next_category, count(*) from civicrm_contact_category group by next_category")->fetchAll();
$summary['changes'] = $n; $summary['changes'] = $n;
$_ = memory_get_peak_usage(TRUE);
$summary['memory_use'] = @round($_ / pow(1024, ($i = floor(log($_, 1024)))), 2) . ' ' . ['b', 'kb', 'mb', 'gb', 'tb', 'pb'][$i];
Civi::log()->debug('Complete.', ['=' => 'set']);
$result->exchangeArray($summary); $result->exchangeArray($summary);
} }

View file

@ -10,17 +10,14 @@ return [
'params' => [ 'params' => [
'version' => 4, 'version' => 4,
'values' => [ 'values' => [
'option_group_id.name' => 'activity_type', 'option_group_id:name' => 'activity_type',
'label' => E::ts('Changed Contact Category'), 'label' => E::ts('Changed Contact Category'),
'value' => '57',
'name' => 'changed_contact_category', 'name' => 'changed_contact_category',
'weight' => 57,
'icon' => 'fa-tags', 'icon' => 'fa-tags',
], ],
'match' => [ 'match' => [
'option_group_id', 'option_group_id',
'name', 'name',
'value',
], ],
], ],
], ],