Get project list for guessing groups from in memory project cache

At the moment guessing relevant groups first gets the list of all
projects, then for each project it gets the groups of the project, but
only if it is present in the in-memory cache. Getting the list of all
projects can be slow if it’s not cached yet (since the projects need to
be loaded from the storage layer, e.g. by scanning the repository
directories on disc). Since projects that are not present in the
in-memory cache are skipped, we can just skip getting the list of all
projects and instead directly get the groups from all projects that are
present in the in-memory cache.

Release-Notes: Get project list for guessing groups from in memory project cache
Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: I8feeea2fb6a8073cf24b3468a38735c80eff7347
diff --git a/java/com/google/gerrit/server/project/ProjectCacheImpl.java b/java/com/google/gerrit/server/project/ProjectCacheImpl.java
index 6498d1b..0afaa3f 100644
--- a/java/com/google/gerrit/server/project/ProjectCacheImpl.java
+++ b/java/com/google/gerrit/server/project/ProjectCacheImpl.java
@@ -76,6 +76,7 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Stream;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.Config;
@@ -300,19 +301,20 @@
   @Override
   public Set<AccountGroup.UUID> guessRelevantGroupUUIDs() {
     try (Timer0.Context ignored = guessRelevantGroupsLatency.start()) {
+      Stream<AccountGroup.UUID> configuredRelevantGroups =
+          Arrays.stream(config.getStringList("groups", /* subsection= */ null, "relevantGroup"))
+              .map(AccountGroup::uuid);
+
+      Stream<AccountGroup.UUID> guessedRelevantGroups =
+          inMemoryProjectCache.asMap().values().stream()
+              .filter(Objects::nonNull)
+              .flatMap(p -> p.getAllGroupUUIDs().stream())
+              // getAllGroupUUIDs shouldn't really return null UUIDs, but harden
+              // against them just in case there is a bug or corner case.
+              .filter(id -> id != null && id.get() != null);
+
       Set<AccountGroup.UUID> relevantGroupUuids =
-          Streams.concat(
-                  Arrays.stream(
-                          config.getStringList("groups", /* subsection= */ null, "relevantGroup"))
-                      .map(AccountGroup::uuid),
-                  all().stream()
-                      .map(n -> inMemoryProjectCache.getIfPresent(n))
-                      .filter(Objects::nonNull)
-                      .flatMap(p -> p.getAllGroupUUIDs().stream())
-                      // getAllGroupUUIDs shouldn't really return null UUIDs, but harden
-                      // against them just in case there is a bug or corner case.
-                      .filter(id -> id != null && id.get() != null))
-              .collect(toSet());
+          Streams.concat(configuredRelevantGroups, guessedRelevantGroups).collect(toSet());
       logger.atFine().log("relevant group UUIDs: %s", relevantGroupUuids);
       return relevantGroupUuids;
     }