Optimize the 'path_owners_entries' cache eviction The OWNERS file can be present either under the `refs/meta/config` or `refs/heads/*` ref. Ignore evictions to All-Users project and to other (gerrit technical refs). Bug: Issue 16830 Change-Id: I2c2d4a6ec3950f7890ae1d8e372f71bffcc7796b
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntriesCache.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntriesCache.java index 07be702..c2ec085 100644 --- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntriesCache.java +++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntriesCache.java
@@ -15,11 +15,13 @@ package com.googlesource.gerrit.owners.common; import com.google.common.cache.RemovalNotification; +import com.google.gerrit.entities.RefNames; import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.extensions.events.GitReferenceUpdatedListener; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.server.cache.CacheModule; import com.google.gerrit.server.cache.CacheRemovalListener; +import com.google.gerrit.server.config.AllUsersName; import com.google.inject.Inject; import com.google.inject.Module; import com.google.inject.Singleton; @@ -103,15 +105,25 @@ @Singleton class OwnersRefUpdateListener implements GitReferenceUpdatedListener { private final PathOwnersEntriesCache cache; + private final String allUsersName; @Inject - OwnersRefUpdateListener(PathOwnersEntriesCache cache) { + OwnersRefUpdateListener(PathOwnersEntriesCache cache, AllUsersName allUsersName) { this.cache = cache; + this.allUsersName = allUsersName.get(); } @Override public void onGitReferenceUpdated(Event event) { - cache.invalidate(event.getProjectName(), event.getRefName()); + if (supportedEvent(allUsersName, event)) { + cache.invalidate(event.getProjectName(), event.getRefName()); + } + } + + static boolean supportedEvent(String allUsersName, Event event) { + String refName = event.getRefName(); + return !allUsersName.equals(event.getProjectName()) + && (refName.equals(RefNames.REFS_CONFIG) || !RefNames.isGerritRef(refName)); } }
diff --git a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/OwnersRefUpdateListenerTest.java b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/OwnersRefUpdateListenerTest.java new file mode 100644 index 0000000..fa20c79 --- /dev/null +++ b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/OwnersRefUpdateListenerTest.java
@@ -0,0 +1,72 @@ +// Copyright (C) 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.googlesource.gerrit.owners.common; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.gerrit.entities.RefNames; +import com.google.gerrit.extensions.events.GitReferenceUpdatedListener; +import com.google.gerrit.server.config.AllProjectsNameProvider; +import com.google.gerrit.server.config.AllUsersNameProvider; +import com.googlesource.gerrit.owners.common.PathOwnersEntriesCache.OwnersRefUpdateListener; +import java.util.Arrays; +import java.util.Collection; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class OwnersRefUpdateListenerTest { + @Parameterized.Parameters + public static Collection<Object[]> events() { + return Arrays.asList( + new Object[][] { + {mockEvent(ALL_USERS_NAME, null), false}, + {mockEvent(AllProjectsNameProvider.DEFAULT, RefNames.REFS_CHANGES), false}, + {mockEvent(AllProjectsNameProvider.DEFAULT, RefNames.REFS_SEQUENCES), false}, + {mockEvent(AllProjectsNameProvider.DEFAULT, RefNames.REFS_CONFIG), true}, + {mockEvent("foo", RefNames.fullName("bar")), true}, + {mockEvent("foo", RefNames.REFS_CONFIG), true} + }); + } + + private static String ALL_USERS_NAME = AllUsersNameProvider.DEFAULT; + + private final GitReferenceUpdatedListener.Event input; + private final boolean expected; + + public OwnersRefUpdateListenerTest(GitReferenceUpdatedListener.Event input, boolean expected) { + this.input = input; + this.expected = expected; + } + + @Test + public void shouldParseLabelDefinition() { + // when + boolean result = OwnersRefUpdateListener.supportedEvent(ALL_USERS_NAME, input); + + // then + assertThat(result).isEqualTo(expected); + } + + private static GitReferenceUpdatedListener.Event mockEvent(String project, String ref) { + GitReferenceUpdatedListener.Event eventMock = mock(GitReferenceUpdatedListener.Event.class); + when(eventMock.getProjectName()).thenReturn(project); + when(eventMock.getRefName()).thenReturn(ref); + return eventMock; + } +}