Allow to enable/disable push/pull replication filters The multi-site plugin had always enabled all replication filtering with the checking of their global-refdb status. Although it is a good default to have, the lack of flexibility brought some additional performance issues when running unneeded checks of hundreds of thousands of refs against the global-refdb. Example: the replication endpoint is not Gerrit or is a Gerrit replica, therefore there is no need to integrate and check with the global-refdb consistency, because the endpoint won't be tracked under it anyway. On Cloud environments where the global-refdb is provided as a service, the consumption of the APIs is very expensive and can also be capped or rate-limited, causing potential outages due to unneeded calls. Introduce two new settings for enabling/disabling the filtering individually for the push or pull-replication plugins. Example: [ref-database] pushReplicationFilterClassEnabled = false Change-Id: I1989f3bbc8c257f9bb5847e7d3c7755464e2cf3a
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/Configuration.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/Configuration.java index a7a05d3..dd694f6 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/multisite/Configuration.java +++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/Configuration.java
@@ -58,6 +58,8 @@ private static final String REPLICATION_LAG_REFRESH_INTERVAL = "replicationLagRefreshInterval"; private static final String REPLICATION_LAG_ENABLED = "replicationLagEnabled"; private static final Duration REPLICATION_LAG_REFRESH_INTERVAL_DEFAULT = Duration.ofSeconds(60); + private static final String PUSH_REPLICATION_FILTER_ENABLED = "pushReplicationFilterEnabled"; + private static final String PULL_REPLICATION_FILTER_ENABLED = "pullReplicationFilterEnabled"; private static final String REPLICATION_CONFIG = "replication.config"; // common parameters to cache and index sections @@ -79,6 +81,8 @@ private final Config multiSiteConfig; private final Supplier<Duration> replicationLagRefreshInterval; private final Supplier<Boolean> replicationLagEnabled; + private final Supplier<Boolean> pushReplicationFilterEnabled; + private final Supplier<Boolean> pullReplicationFilterEnabled; @Inject Configuration(SitePaths sitePaths) { @@ -118,6 +122,19 @@ lazyMultiSiteCfg .get() .getBoolean(REF_DATABASE, null, REPLICATION_LAG_ENABLED, true)); + + pushReplicationFilterEnabled = + memoize( + () -> + lazyMultiSiteCfg + .get() + .getBoolean(REF_DATABASE, null, PUSH_REPLICATION_FILTER_ENABLED, true)); + pullReplicationFilterEnabled = + memoize( + () -> + lazyMultiSiteCfg + .get() + .getBoolean(REF_DATABASE, null, PULL_REPLICATION_FILTER_ENABLED, true)); } public Config getMultiSiteConfig() { @@ -160,6 +177,14 @@ return replicationLagEnabled.get(); } + public boolean pushReplicationFilterEnabled() { + return pushReplicationFilterEnabled.get(); + } + + public boolean pullRepllicationFilterEnabled() { + return pullReplicationFilterEnabled.get(); + } + public Collection<Message> validate() { return replicationConfigValidation.get(); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginModule.java index db06c9f..3ced8c6 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginModule.java +++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginModule.java
@@ -35,14 +35,10 @@ public class PluginModule extends LifecycleModule { private static final FluentLogger log = FluentLogger.forEnclosingClass(); - private static final String[] FILTER_MODULES_CLASS_NAMES = - new String[] { - /* Class names are defined as String for avoiding this class failing to load - * if either replication or pull-replication plugins are missing. - */ - "com.googlesource.gerrit.plugins.multisite.validation.PullReplicationFilterModule", - "com.googlesource.gerrit.plugins.multisite.validation.PushReplicationFilterModule" - }; + public static final String PULL_REPLICATION_FILTER_MODULE = + "com.googlesource.gerrit.plugins.multisite.validation.PullReplicationFilterModule"; + public static final String PUSH_REPLICATION_FILTER_MODULE = + "com.googlesource.gerrit.plugins.multisite.validation.PushReplicationFilterModule"; private final Configuration config; private final WorkQueue workQueue; @@ -89,25 +85,33 @@ private Iterable<AbstractModule> detectFilterModules() { ImmutableList.Builder<AbstractModule> filterModulesBuilder = ImmutableList.builder(); - for (String filterClassName : FILTER_MODULES_CLASS_NAMES) { - try { - @SuppressWarnings("unchecked") - Class<AbstractModule> filterClass = (Class<AbstractModule>) Class.forName(filterClassName); - - AbstractModule filterModule = parentInjector.getInstance(filterClass); - // Check if the filterModule would be valid for creating a child Guice Injector - parentInjector.createChildInjector(filterModule); - - filterModulesBuilder.add(filterModule); - } catch (NoClassDefFoundError | ClassNotFoundException e) { - log.atFine().withCause(e).log( - "Not loading %s because of missing the associated replication plugin", filterClassName); - } catch (Exception e) { - throw new ProvisionException( - "Unable to instantiate replication filter " + filterClassName, e); - } + if (config.pushReplicationFilterEnabled()) { + bindReplicationFilterClass(PUSH_REPLICATION_FILTER_MODULE, filterModulesBuilder); + } + if (config.pullRepllicationFilterEnabled()) { + bindReplicationFilterClass(PULL_REPLICATION_FILTER_MODULE, filterModulesBuilder); } return filterModulesBuilder.build(); } + + private void bindReplicationFilterClass( + String filterClassName, ImmutableList.Builder<AbstractModule> filterModulesBuilder) { + try { + @SuppressWarnings("unchecked") + Class<AbstractModule> filterClass = (Class<AbstractModule>) Class.forName(filterClassName); + + AbstractModule filterModule = parentInjector.getInstance(filterClass); + // Check if the filterModule would be valid for creating a child Guice Injector + parentInjector.createChildInjector(filterModule); + + filterModulesBuilder.add(filterModule); + } catch (NoClassDefFoundError | ClassNotFoundException e) { + log.atWarning().withCause(e).log( + "Not loading %s because of missing the associated replication plugin", filterClassName); + } catch (Exception e) { + throw new ProvisionException( + "Unable to instantiate replication filter " + filterClassName, e); + } + } }
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md index 7547fd9..d7f72aa 100644 --- a/src/main/resources/Documentation/config.md +++ b/src/main/resources/Documentation/config.md
@@ -95,6 +95,16 @@ : Enable the use of a shared ref-database Defaults: true +```ref-database.pushReplicationFilterClassEnabled``` +: Enable the filtering of push replication events checking their + up-to-date status with the global-refdb. + Defaults: true + +```ref-database.pullReplicationFilterClassEnabled``` +: Enable the filtering of pull replication events checking their + up-to-date status with the global-refdb. + Defaults: true + ```ref-database.replicationLagEnabled``` : Enable the metrics to trace the auto-replication lag between sites updating the `refs/multi-site/version/*` to the _epoch_ timestamp in