Index change upon propagation
When a change gets replicated from one master to another
the change needs to be automatically reindexed on the destination instance.
Feature: Issue 11616
Change-Id: I5373bb8149ce5096e3e4a34d214540cc9639ea89
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchRefReplicatedEvent.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchRefReplicatedEvent.java
index eb825b8..cad6dfb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchRefReplicatedEvent.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchRefReplicatedEvent.java
@@ -42,6 +42,10 @@
this.refUpdateResult = refUpdateResult;
}
+ public String getStatus() {
+ return status;
+ }
+
@Override
public int hashCode() {
return Objects.hash(project, ref, status, refUpdateResult);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
index 9add07c..816aaca 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
@@ -44,6 +44,7 @@
import com.googlesource.gerrit.plugins.replication.pull.client.FetchRestApiClient;
import com.googlesource.gerrit.plugins.replication.pull.client.HttpClient;
import com.googlesource.gerrit.plugins.replication.pull.client.SourceHttpClient;
+import com.googlesource.gerrit.plugins.replication.pull.event.FetchRefReplicatedEventModule;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
@@ -67,6 +68,8 @@
install(new PullReplicationApiModule());
+ install(new FetchRefReplicatedEventModule());
+
install(
new FactoryModuleBuilder()
.implement(HttpClient.class, SourceHttpClient.class)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandler.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandler.java
new file mode 100644
index 0000000..fc96394
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandler.java
@@ -0,0 +1,58 @@
+// Copyright (C) 2021 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.plugins.replication.pull.event;
+
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.entities.Change;
+import com.google.gerrit.entities.Project;
+import com.google.gerrit.server.events.Event;
+import com.google.gerrit.server.events.EventListener;
+import com.google.gerrit.server.index.change.ChangeIndexer;
+import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.replication.pull.FetchRefReplicatedEvent;
+import com.googlesource.gerrit.plugins.replication.pull.ReplicationState;
+
+public class FetchRefReplicatedEventHandler implements EventListener {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+ private ChangeIndexer changeIndexer;
+
+ @Inject
+ FetchRefReplicatedEventHandler(ChangeIndexer changeIndexer) {
+ this.changeIndexer = changeIndexer;
+ }
+
+ @Override
+ public void onEvent(Event event) {
+ if (event instanceof FetchRefReplicatedEvent) {
+ FetchRefReplicatedEvent fetchRefReplicatedEvent = (FetchRefReplicatedEvent) event;
+ Project.NameKey projectNameKey = fetchRefReplicatedEvent.getProjectNameKey();
+ logger.atFine().log(
+ "Indexing ref '%s' for project %s",
+ fetchRefReplicatedEvent.getRefName(), projectNameKey.get());
+
+ Change.Id changeId = Change.Id.fromRef(fetchRefReplicatedEvent.getRefName());
+ if (changeId != null
+ && fetchRefReplicatedEvent
+ .getStatus()
+ .equals(ReplicationState.RefFetchResult.SUCCEEDED.toString())) {
+ changeIndexer.index(projectNameKey, changeId);
+ } else {
+ logger.atWarning().log(
+ "Couldn't get changeId from refName. Skipping indexing of change %s for project %s",
+ fetchRefReplicatedEvent.getRefName(), projectNameKey.get());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventModule.java
new file mode 100644
index 0000000..675563a
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventModule.java
@@ -0,0 +1,27 @@
+// Copyright (C) 2021 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.plugins.replication.pull.event;
+
+import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gerrit.lifecycle.LifecycleModule;
+import com.google.gerrit.server.events.EventListener;
+
+public class FetchRefReplicatedEventModule extends LifecycleModule {
+
+ @Override
+ protected void configure() {
+ DynamicSet.bind(binder(), EventListener.class).to(FetchRefReplicatedEventHandler.class);
+ }
+}
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index d921e0b..22b52e7 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -15,3 +15,8 @@
To be allowed to trigger pull replication a user must be a member of a
group that is granted the 'Pull Replication' capability (provided
by this plugin) or the 'Administrate Server' capability.
+
+Change Indexing
+--------
+
+Changes will be automatically indexed upon replication.
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandlerTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandlerTest.java
new file mode 100644
index 0000000..1d87195
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandlerTest.java
@@ -0,0 +1,97 @@
+// Copyright (C) 2021 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.plugins.replication.pull.event;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import com.google.gerrit.entities.Change;
+import com.google.gerrit.entities.Project;
+import com.google.gerrit.server.index.change.ChangeIndexer;
+import com.googlesource.gerrit.plugins.replication.pull.FetchRefReplicatedEvent;
+import com.googlesource.gerrit.plugins.replication.pull.ReplicationState;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FetchRefReplicatedEventHandlerTest {
+ private ChangeIndexer changeIndexerMock;
+ private FetchRefReplicatedEventHandler fetchRefReplicatedEventHandler;
+
+ @Before
+ public void setUp() throws Exception {
+ changeIndexerMock = mock(ChangeIndexer.class);
+ fetchRefReplicatedEventHandler = new FetchRefReplicatedEventHandler(changeIndexerMock);
+ }
+
+ @Test
+ public void onEventShouldIndexExistingChange() {
+ Project.NameKey projectNameKey = Project.nameKey("testProject");
+ String ref = "refs/changes/41/41/meta";
+ Change.Id changeId = Change.Id.fromRef(ref);
+ fetchRefReplicatedEventHandler.onEvent(
+ new FetchRefReplicatedEvent(
+ projectNameKey.get(),
+ ref,
+ "aSourceNode",
+ ReplicationState.RefFetchResult.SUCCEEDED,
+ RefUpdate.Result.FAST_FORWARD));
+ verify(changeIndexerMock, times(1)).index(eq(projectNameKey), eq(changeId));
+ }
+
+ @Test
+ public void onEventShouldNotIndexMissingChange() {
+ fetchRefReplicatedEventHandler.onEvent(
+ new FetchRefReplicatedEvent(
+ Project.nameKey("testProject").get(),
+ "invalidRef",
+ "aSourceNode",
+ ReplicationState.RefFetchResult.SUCCEEDED,
+ RefUpdate.Result.FAST_FORWARD));
+ verify(changeIndexerMock, never()).index(any(), any());
+ }
+
+ @Test
+ public void onEventShouldNotIndexFailingChange() {
+ Project.NameKey projectNameKey = Project.nameKey("testProject");
+ String ref = "refs/changes/41/41/meta";
+ fetchRefReplicatedEventHandler.onEvent(
+ new FetchRefReplicatedEvent(
+ projectNameKey.get(),
+ ref,
+ "aSourceNode",
+ ReplicationState.RefFetchResult.FAILED,
+ RefUpdate.Result.FAST_FORWARD));
+ verify(changeIndexerMock, never()).index(any(), any());
+ }
+
+ @Test
+ public void onEventShouldNotIndexNotAttemptedChange() {
+ Project.NameKey projectNameKey = Project.nameKey("testProject");
+ String ref = "refs/changes/41/41/meta";
+ fetchRefReplicatedEventHandler.onEvent(
+ new FetchRefReplicatedEvent(
+ projectNameKey.get(),
+ ref,
+ "aSourceNode",
+ ReplicationState.RefFetchResult.NOT_ATTEMPTED,
+ RefUpdate.Result.FAST_FORWARD));
+ verify(changeIndexerMock, never()).index(any(), any());
+ }
+}