Merge branch 'stable-3.8' into stable-3.9

* stable-3.8:
  Do not exceed index.maxTerms when querying group index by subgroups

Release-Notes: skip
Change-Id: Ia8471268c938657a092cca43a374ae8dd19620a8
diff --git a/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java b/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
index fc6087b..5134643 100644
--- a/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
+++ b/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
@@ -23,11 +23,13 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.AccountGroup;
 import com.google.gerrit.entities.InternalGroup;
+import com.google.gerrit.index.IndexConfig;
 import com.google.gerrit.proto.Protos;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.gerrit.server.cache.proto.Cache.AllExternalGroupsProto;
@@ -45,9 +47,11 @@
 import com.google.inject.Singleton;
 import com.google.inject.TypeLiteral;
 import com.google.inject.name.Named;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
@@ -62,6 +66,8 @@
   private static final String EXTERNAL_NAME = "groups_external";
   private static final String PERSISTED_EXTERNAL_NAME = "groups_external_persisted";
 
+  private final IndexConfig indexConfig;
+
   public static Module module() {
     return new CacheModule() {
       @Override
@@ -115,10 +121,12 @@
           LoadingCache<Account.Id, ImmutableSet<AccountGroup.UUID>> groupsWithMember,
       @Named(PARENT_GROUPS_NAME)
           LoadingCache<AccountGroup.UUID, ImmutableSet<AccountGroup.UUID>> parentGroups,
-      @Named(EXTERNAL_NAME) LoadingCache<String, ImmutableList<AccountGroup.UUID>> external) {
+      @Named(EXTERNAL_NAME) LoadingCache<String, ImmutableList<AccountGroup.UUID>> external,
+      IndexConfig indexConfig) {
     this.groupsWithMember = groupsWithMember;
     this.parentGroups = parentGroups;
     this.external = external;
+    this.indexConfig = indexConfig;
   }
 
   @Override
@@ -145,7 +153,10 @@
   public Collection<AccountGroup.UUID> parentGroupsOf(Set<AccountGroup.UUID> groupIds) {
     try {
       Set<AccountGroup.UUID> parents = new HashSet<>();
-      parentGroups.getAll(groupIds).values().forEach(p -> parents.addAll(p));
+      for (List<AccountGroup.UUID> groupIdsBatch :
+          Lists.partition(new ArrayList<>(groupIds), indexConfig.maxTerms())) {
+        parentGroups.getAll(groupIdsBatch).values().forEach(p -> parents.addAll(p));
+      }
       return parents;
     } catch (ExecutionException e) {
       logger.atWarning().withCause(e).log("Cannot load included groups");