Add an isCacheableByBranch() to the PredicateCache Add an API to determine if a Predicate's output is assumed to be constant given any Change destined for the same Branch.NameKey. Change-Id: I32b52fe04742a344e71a4eee9bc2b69133d112ff
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java b/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java index aa3da13..f6d6259 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java +++ b/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
@@ -14,27 +14,50 @@ package com.googlesource.gerrit.plugins.task; +import com.google.gerrit.extensions.annotations.PluginName; +import com.google.gerrit.index.query.AndPredicate; +import com.google.gerrit.index.query.NotPredicate; +import com.google.gerrit.index.query.OrPredicate; import com.google.gerrit.index.query.Predicate; import com.google.gerrit.index.query.QueryParseException; import com.google.gerrit.server.CurrentUser; +import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeQueryBuilder; +import com.google.gerrit.server.query.change.DestinationPredicate; +import com.google.gerrit.server.query.change.ProjectPredicate; +import com.google.gerrit.server.query.change.RefPredicate; +import com.google.gerrit.server.query.change.RegexProjectPredicate; +import com.google.gerrit.server.query.change.RegexRefPredicate; import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; +import org.eclipse.jgit.lib.Config; public class PredicateCache { protected final ChangeQueryBuilder cqb; + protected final Set<String> cacheableByBranchPredicateClassNames; protected final CurrentUser user; protected final Map<String, ThrowingProvider<Predicate<ChangeData>, QueryParseException>> predicatesByQuery = new HashMap<>(); @Inject - public PredicateCache(CurrentUser user, ChangeQueryBuilder cqb) { + public PredicateCache( + @GerritServerConfig Config config, + @PluginName String pluginName, + CurrentUser user, + ChangeQueryBuilder cqb) { this.user = user; this.cqb = cqb; + cacheableByBranchPredicateClassNames = + new HashSet<>( + Arrays.asList( + config.getStringList(pluginName, "cacheable-predicates", "byBranch-className"))); } public boolean match(ChangeData c, String query) throws OrmException, QueryParseException { @@ -78,4 +101,39 @@ throw e; } } + + /** + * Can this query's output be assumed to be constant given any Change destined for the same + * Branch.NameKey? + */ + public boolean isCacheableByBranch(String query) throws QueryParseException { + if (query == null + || "".equals(query) + || "false".equalsIgnoreCase(query) + || "true".equalsIgnoreCase(query)) { + return true; + } + return isCacheableByBranch(getPredicate(query)); + } + + protected boolean isCacheableByBranch(Predicate<ChangeData> predicate) { + if (predicate instanceof AndPredicate + || predicate instanceof NotPredicate + || predicate instanceof OrPredicate) { + for (Predicate<ChangeData> subPred : predicate.getChildren()) { + if (!isCacheableByBranch(subPred)) { + return false; + } + } + return true; + } + if (predicate instanceof DestinationPredicate + || predicate instanceof ProjectPredicate + || predicate instanceof RefPredicate + || predicate instanceof RegexProjectPredicate + || predicate instanceof RegexRefPredicate) { + return true; + } + return cacheableByBranchPredicateClassNames.contains(predicate.getClass().getName()); + } }
diff --git a/src/main/resources/Documentation/config-gerrit.md b/src/main/resources/Documentation/config-gerrit.md new file mode 100644 index 0000000..6f0b0a5 --- /dev/null +++ b/src/main/resources/Documentation/config-gerrit.md
@@ -0,0 +1,25 @@ +# Admin User Guide - Configuration + +## File `etc/gerrit.config` + +The file `'$site_path'/etc/gerrit.config` is a Git-style config file +that controls many host specific settings for Gerrit. + +### Section @PLUGIN@ "cacheable-predicates" + +The @PLUGIN@.cacheable-predicates section configures Change Predicate +optimizations which the @PLUGIN@ plugin may use when evaluating tasks. + +#### @PLUGIN@.cacheable-predicates.byBranch-className + +The value set with this key specifies a fully qualified class name +of a Predicate which can be assumed to always return the same match +result to all Changes destined for the same project/branch +combinations. This key may be specified more than once. + +Example: + +``` +[@PLUGIN@ "cacheable-predicates"] + byBranch-className = com.google.gerrit.server.query.change.BranchSetPredicate +``` \ No newline at end of file