Move ForwarderIndexProjectHandler to use common retry logic
Adapt IndexProjecthandler to use common retry functionality by extending
the ForwardedIndexingHandlerWithRetries.
Bug: Issue 14332
Change-Id: Id62f5bc298a3755ee5d24d16787286ada263d95f
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandler.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandler.java
index ce6804e..3787a80 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandler.java
@@ -16,6 +16,7 @@
import com.google.gerrit.entities.Project;
import com.google.gerrit.index.project.ProjectIndexer;
+import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.multisite.Configuration;
@@ -24,7 +25,6 @@
import com.googlesource.gerrit.plugins.multisite.index.ProjectChecker;
import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
/**
* Index a project using {@link ProjectIndexer}. This class is meant to be used on the receiving
@@ -34,78 +34,40 @@
*/
@Singleton
public class ForwardedIndexProjectHandler
- extends ForwardedIndexingHandler<String, ProjectIndexEvent> {
+ extends ForwardedIndexingHandlerWithRetries<String, ProjectIndexEvent> {
private final ProjectIndexer indexer;
- private final int retryInterval;
- private final int maxTries;
private final ProjectChecker projectChecker;
- private final ScheduledExecutorService indexExecutor;
@Inject
ForwardedIndexProjectHandler(
ProjectIndexer indexer,
ProjectChecker projectChecker,
+ OneOffRequestContext oneOffRequestContext,
@ForwardedIndexExecutor ScheduledExecutorService indexExecutor,
Configuration config) {
- super(config.index().numStripedLocks());
+ super(indexExecutor, config, oneOffRequestContext);
this.indexer = indexer;
- Configuration.Index indexConfig = config.index();
- this.retryInterval = indexConfig != null ? indexConfig.retryInterval() : 0;
- this.maxTries = indexConfig != null ? indexConfig.maxTries() : 0;
- this.indexExecutor = indexExecutor;
this.projectChecker = projectChecker;
}
@Override
protected void doIndex(String projectName, Optional<ProjectIndexEvent> event) {
- if (!attemptIndex(projectName, event)) {
- log.warn("First Attempt failed, scheduling again after {} msecs", retryInterval);
- rescheduleIndex(projectName, event, 1);
- }
+ attemptToIndex(projectName, event, 0);
}
- public boolean attemptIndex(String projectName, Optional<ProjectIndexEvent> event) {
- log.debug("Attempt to index project {}, event: [{}]", projectName, event);
- final Project.NameKey projectNameKey = Project.nameKey(projectName);
- if (projectChecker.isProjectUpToDate(projectNameKey)) {
- indexer.index(projectNameKey);
- log.debug("Project {} successfully indexed", projectName);
- return true;
- }
- return false;
+ @Override
+ protected void reindex(String id) {
+ indexer.index(Project.nameKey(id));
}
- public void rescheduleIndex(
- String projectName, Optional<ProjectIndexEvent> event, int retryCount) {
- if (retryCount > maxTries) {
- log.error(
- "Project {} could not be indexed after {} retries. index could be stale.",
- projectName,
- retryCount);
+ @Override
+ protected String indexName() {
+ return "project";
+ }
- return;
- }
-
- log.warn(
- "Retrying for the #{} time to index project {} after {} msecs",
- retryCount,
- projectName,
- retryInterval);
-
- indexExecutor.schedule(
- () -> {
- Context.setForwardedEvent(true);
- if (!attemptIndex(projectName, event)) {
- log.warn(
- "Attempt {} to index project {} failed, scheduling again after {} msecs",
- retryCount,
- projectName,
- retryInterval);
- rescheduleIndex(projectName, event, retryCount + 1);
- }
- },
- retryInterval,
- TimeUnit.MILLISECONDS);
+ @Override
+ protected void attemptToIndex(String id, Optional<ProjectIndexEvent> indexEvent, int retryCount) {
+ reindexAndCheckIsUpToDate(id, indexEvent, projectChecker, retryCount);
}
@Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ProjectChecker.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ProjectChecker.java
index ece2443..e040fce 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ProjectChecker.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ProjectChecker.java
@@ -14,9 +14,7 @@
package com.googlesource.gerrit.plugins.multisite.index;
-import com.google.gerrit.entities.Project;
+import com.googlesource.gerrit.plugins.multisite.forwarder.events.ProjectIndexEvent;
/** Encapsulates the logic of verifying the up-to-date status of a project. */
-public interface ProjectChecker {
- boolean isProjectUpToDate(Project.NameKey projectName);
-}
+public interface ProjectChecker extends UpToDateChecker<ProjectIndexEvent> {}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ProjectCheckerImpl.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ProjectCheckerImpl.java
index 548ccc0..ba2a7d6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ProjectCheckerImpl.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ProjectCheckerImpl.java
@@ -17,6 +17,8 @@
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.project.ProjectCache;
import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.multisite.forwarder.events.ProjectIndexEvent;
+import java.util.Optional;
public class ProjectCheckerImpl implements ProjectChecker {
private final ProjectCache projectCache;
@@ -27,7 +29,7 @@
}
@Override
- public boolean isProjectUpToDate(Project.NameKey projectName) {
- return projectCache.get(projectName) != null;
+ public boolean isUpToDate(Optional<ProjectIndexEvent> indexEvent) {
+ return indexEvent.map(e -> Project.nameKey(e.projectName)).map(projectCache::get).isPresent();
}
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandlerTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandlerTest.java
index 1102cd2..3ce5e14 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandlerTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandlerTest.java
@@ -23,6 +23,7 @@
import com.google.gerrit.entities.Project;
import com.google.gerrit.index.project.ProjectIndexer;
+import com.google.gerrit.server.util.OneOffRequestContext;
import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.forwarder.ForwardedIndexingHandler.Operation;
import com.googlesource.gerrit.plugins.multisite.index.ProjectChecker;
@@ -44,6 +45,7 @@
@Rule public ExpectedException exception = ExpectedException.none();
@Mock private ProjectIndexer indexerMock;
@Mock private Configuration configMock;
+ @Mock private OneOffRequestContext ctxMock;
@Mock private ProjectChecker projectCheckerMock;
@Mock private Configuration.Index indexMock;
@Mock private ScheduledExecutorService indexExecutorMock;
@@ -56,10 +58,10 @@
when(indexMock.numStripedLocks()).thenReturn(10);
when(indexMock.retryInterval()).thenReturn(0);
when(indexMock.maxTries()).thenReturn(2);
- when(projectCheckerMock.isProjectUpToDate(any())).thenReturn(true);
+ when(projectCheckerMock.isUpToDate(any())).thenReturn(true);
handler =
new ForwardedIndexProjectHandler(
- indexerMock, projectCheckerMock, indexExecutorMock, configMock);
+ indexerMock, projectCheckerMock, ctxMock, indexExecutorMock, configMock);
nameKey = "project/name";
}
@@ -116,13 +118,4 @@
verify(indexerMock).index(Project.nameKey(nameKey));
}
-
- @Test
- public void indexAttemptShouldFailWhenCheckerFails() throws Exception {
- handler =
- new ForwardedIndexProjectHandler(
- indexerMock, (projectName) -> false, indexExecutorMock, configMock);
-
- assertThat(handler.attemptIndex(nameKey, Optional.empty())).isFalse();
- }
}