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(); - } }