dev/core#2477 Add setting to allow opportunistic cache flushing for acls
authoreileen <emcnaughton@wikimedia.org>
Sun, 28 Mar 2021 20:37:42 +0000 (09:37 +1300)
committereileen <emcnaughton@wikimedia.org>
Sun, 28 Mar 2021 20:43:57 +0000 (09:43 +1300)
This adds the same mechanism as the group contact cache to reduce site contention.
A job api is also added which people can optionally configure.

It would be especially worth setting on sites that do not use ACLs at all

CRM/ACL/BAO/Cache.php
CRM/Contact/BAO/Contact/Utils.php
api/v3/Job.php
settings/Core.setting.php

index 0daeedffd9e84aadf1b9b393a3aa5c2d96f290ce..af12925101a8f46b4c9f4dc0a5ada9d1a01d983b 100644 (file)
@@ -115,10 +115,23 @@ WHERE contact_id = %1
     CRM_Core_DAO::executeQuery($query, $params);
   }
 
+  /**
+   * Do an opportunistic cache refresh if the site is configured for these.
+   *
+   * Sites that use acls and do not run the acl cache clearing cron job should
+   * refresh the caches on demand. The user session will be forced to wait
+   * and this is a common source of deadlocks, so it is less ideal.
+   */
+  public static function opportunisticCacheFlush(): void {
+    if (Civi::settings()->get('acl_cache_refresh_mode') === 'opportunistic') {
+      self::resetCache();
+    }
+  }
+
   /**
    * Deletes all the cache entries.
    */
-  public static function resetCache() {
+  public static function resetCache(): void {
     if (!CRM_Core_Config::isPermitCacheFlushMode()) {
       return;
     }
index 5ffd18002cc59bd7f75ca09ce3d2ca10d0821b89..704b688f995a422d809af2f16600cf39894bb37d 100644 (file)
@@ -866,7 +866,7 @@ INNER JOIN civicrm_contact contact_target ON ( contact_target.id = act.contact_i
    *   likely affect user experience in unexpected ways. Existing behaviour retained
    *   ... reluctantly.
    */
-  public static function clearContactCaches($isEmptyPrevNextTable = FALSE) {
+  public static function clearContactCaches($isEmptyPrevNextTable = FALSE): void {
     if (!CRM_Core_Config::isPermitCacheFlushMode()) {
       return;
     }
@@ -876,8 +876,8 @@ INNER JOIN civicrm_contact contact_target ON ( contact_target.id = act.contact_i
       Civi::service('prevnext')->deleteItem();
       CRM_Core_BAO_PrevNextCache::deleteItem();
     }
-    // clear acl cache if any.
-    CRM_ACL_BAO_Cache::resetCache();
+
+    CRM_ACL_BAO_Cache::opportunisticCacheFlush();
     CRM_Contact_BAO_GroupContactCache::opportunisticCacheFlush();
   }
 
index e791235232659d41f17084fb41d6cd9ee782a646..05d350c0d1f19b80c09387dcc8c6f4773c68aa34 100644 (file)
@@ -711,21 +711,41 @@ function civicrm_api3_job_group_rebuild($params) {
 /**
  * Flush smart groups caches.
  *
- * This job purges aged smart group cache data (based on the timeout value). Sites can decide whether they want this
- * job and / or the group cache rebuild job to run. In some cases performance is better when old caches are cleared out
- * prior to any attempt to rebuild them. Also, many sites are very happy to have caches built on demand, provided the
- * user is not having to wait for deadlocks to clear when invalidating them.
+ * This job purges aged smart group cache data (based on the timeout value).
+ * Sites can decide whether they want this job and / or the group cache rebuild
+ * job to run. In some cases performance is better when old caches are cleared
+ * out prior to any attempt to rebuild them. Also, many sites are very happy to
+ * have caches built on demand, provided the user is not having to wait for
+ * deadlocks to clear when invalidating them.
  *
  * @param array $params
  *
  * @return array
- * @throws \API_Exception
+ * @throws \CiviCRM_API3_Exception
  */
-function civicrm_api3_job_group_cache_flush($params) {
+function civicrm_api3_job_group_cache_flush(array $params): array {
   CRM_Contact_BAO_GroupContactCache::deterministicCacheFlush();
   return civicrm_api3_create_success();
 }
 
+/**
+ * Flush acl caches.
+ *
+ * This job flushes the acl cache. For many sites it is better to do
+ * this by cron (or not at all if acls are not used) than whenever
+ * a contact is edited.
+ *
+ * @param array $params
+ *
+ * @return array
+ *
+ * @throws \CiviCRM_API3_Exception
+ */
+function civicrm_api3_job_acl_cache_flush(array $params): array {
+  CRM_ACL_BAO_Cache::resetCache();
+  return civicrm_api3_create_success();
+}
+
 /**
  * Check for CiviCRM software updates.
  *
index 20b7d50b2412a2d7cbfff46e8c79309d90aee720..4548868072b3829189c1fb3fb1ab2217c16182cf 100644 (file)
@@ -358,9 +358,26 @@ return [
     'pseudoconstant' => [
       'callback' => 'CRM_Contact_BAO_GroupContactCache::getModes',
     ],
-    'description' => ts('Should the smart groups be by cron jobs or user actions'),
+    'description' => ts('Should the smart groups be flushed by cron jobs or user actions'),
     'help_text' => ts('In "Opportunistic Flush" mode, caches are flushed in response to user actions; this mode is broadly compatible but may add latency during form-submissions. In "Cron Flush" mode, you should schedule a cron job to flush caches; this can improve latency on form-submissions but requires more setup.'),
   ],
+  'acl_cache_refresh_mode' => [
+    'group_name' => 'CiviCRM Preferences',
+    'group' => 'core',
+    'name' => 'acl_cache_refresh_mode',
+    'type' => 'String',
+    'html_type' => 'radio',
+    'default' => 'opportunistic',
+    'add' => '5.37.0',
+    'title' => ts('ACL Group Refresh Mode'),
+    'is_domain' => 1,
+    'is_contact' => 0,
+    'pseudoconstant' => [
+      'callback' => 'CRM_Contact_BAO_GroupContactCache::getModes',
+    ],
+    'description' => ts('Should the acl cache be by cron jobs or user actions'),
+    'help_text' => ts('In "Opportunistic Flush" mode, caches are flushed in response to user actions; this mode is broadly compatible but may add latency during form-submissions. In "Cron Flush" mode, you should schedule a cron job to flush caches if your site uses ACLs; this can improve latency on form-submissions but requires more setup.'),
+  ],
   'installed' => [
     'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().',
     'group_name' => 'CiviCRM Preferences',