diff options
author | Jacek <jacek.poreda@sonarsource.com> | 2020-06-08 17:15:43 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2020-06-26 20:04:57 +0000 |
commit | 14d6de3529b12ec0af367e551cf66ac6daae1ca7 (patch) | |
tree | 7674e1e94f2991a2f5819eec401dadd4e0eac86e /server/sonar-webserver-es | |
parent | 52dea5983fffca49138dec3f8b58ed3160c8d37c (diff) | |
download | sonarqube-14d6de3529b12ec0af367e551cf66ac6daae1ca7.tar.gz sonarqube-14d6de3529b12ec0af367e551cf66ac6daae1ca7.zip |
SONAR-13398 fail with 503 api/issues/search WS if needIssueSync is set to true
Diffstat (limited to 'server/sonar-webserver-es')
3 files changed, 132 insertions, 22 deletions
diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/es/EsIndexSyncInProgressException.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/es/EsIndexSyncInProgressException.java index bc75d400841..fe72723b7a7 100644 --- a/server/sonar-webserver-es/src/main/java/org/sonar/server/es/EsIndexSyncInProgressException.java +++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/es/EsIndexSyncInProgressException.java @@ -20,13 +20,14 @@ package org.sonar.server.es; import org.sonar.server.es.IndexType.IndexMainType; +import org.sonar.server.exceptions.ServerException; -public class EsIndexSyncInProgressException extends RuntimeException { +public class EsIndexSyncInProgressException extends ServerException { - private IndexMainType indexType; + private final IndexMainType indexType; - public EsIndexSyncInProgressException(IndexMainType indexType) { - super(String.format("Synchronization of %s index is in progress", indexType.toString())); + public EsIndexSyncInProgressException(IndexMainType indexType, String message) { + super(503, message); this.indexType = indexType; } diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndexSyncProgressChecker.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndexSyncProgressChecker.java index 24e85e69222..6e9ea790226 100644 --- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndexSyncProgressChecker.java +++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndexSyncProgressChecker.java @@ -22,6 +22,7 @@ package org.sonar.server.issue.index; import com.google.common.collect.Sets; import java.util.Collection; import java.util.List; +import javax.annotation.Nullable; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.server.es.EsIndexSyncInProgressException; @@ -39,31 +40,26 @@ public class IssueIndexSyncProgressChecker { return new IssueSyncProgress(completed, total); } - /** - * Checks if issue index sync is in progress, if it is, method throws exception org.sonar.server.es.EsIndexSyncInProgressException - */ - public void checkIfIssueSyncInProgress(DbSession dbSession) throws EsIndexSyncInProgressException { - if (isIssueSyncInProgress(dbSession)) { - throw new EsIndexSyncInProgressException(IssueIndexDefinition.TYPE_ISSUE.getMainType()); + public void checkIfAnyComponentsIssueSyncInProgress(DbSession dbSession, List<String> componentKeys, @Nullable String branch, + @Nullable String pullRequest) { + boolean needIssueSync = dbClient.branchDao().doAnyOfComponentsNeedIssueSync(dbSession, componentKeys, branch, pullRequest); + if (needIssueSync) { + throw new EsIndexSyncInProgressException(IssueIndexDefinition.TYPE_ISSUE.getMainType(), + "Results are temporarily unavailable. Indexing of issues is in progress."); } } /** - * Checks if project issue index sync is in progress, if it is, method throws exception org.sonar.server.es.EsIndexSyncInProgressException + * Checks if issue index sync is in progress, if it is, method throws exception org.sonar.server.es.EsIndexSyncInProgressException */ - public void checkIfProjectIssueSyncInProgress(DbSession dbSession, String projectUuid) throws EsIndexSyncInProgressException { - if (doProjectNeedIssueSync(dbSession, projectUuid)) { - throw new EsIndexSyncInProgressException(IssueIndexDefinition.TYPE_ISSUE.getMainType()); - } - } - - public void checkIfAnyProjectIssueSyncInProgress(DbSession dbSession, Collection<String> projectUuids) throws EsIndexSyncInProgressException { - if (!findProjectUuidsWithIssuesSyncNeed(dbSession, projectUuids).isEmpty()) { - throw new EsIndexSyncInProgressException(IssueIndexDefinition.TYPE_ISSUE.getMainType()); + public void checkIfIssueSyncInProgress(DbSession dbSession) { + if (isIssueSyncInProgress(dbSession)) { + throw new EsIndexSyncInProgressException(IssueIndexDefinition.TYPE_ISSUE.getMainType(), + "Results are temporarily unavailable. Indexing of issues is in progress."); } } - public boolean isIssueSyncInProgress(DbSession dbSession) throws EsIndexSyncInProgressException { + public boolean isIssueSyncInProgress(DbSession dbSession) { return dbClient.branchDao().hasAnyBranchWhereNeedIssueSync(dbSession, true); } diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSyncProgressCheckerTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSyncProgressCheckerTest.java index 3315c8cb37e..d036d47eea0 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSyncProgressCheckerTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSyncProgressCheckerTest.java @@ -22,15 +22,23 @@ package org.sonar.server.issue.index; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.stream.IntStream; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.sonar.api.utils.System2; +import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDto; import org.sonar.db.project.ProjectDto; +import org.sonar.server.es.EsIndexSyncInProgressException; +import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; @RunWith(DataProviderRunner.class) public class IssueIndexSyncProgressCheckerTest { @@ -107,10 +115,115 @@ public class IssueIndexSyncProgressCheckerTest { assertThat(result.isCompleted()).isFalse(); } - private void insertProjectWithBranches(boolean needIssueSync, int numberOfBranches) { + @Test + public void checkIfAnyComponentsIssueSyncInProgress_throws_exception_if_all_components_have_need_issue_sync_TRUE() { + ProjectDto projectDto1 = insertProjectWithBranches(true, 0); + ProjectDto projectDto2 = insertProjectWithBranches(true, 0); + DbSession session = db.getSession(); + List<String> projectKeys = Arrays.asList(projectDto1.getKey(), projectDto2.getKey()); + assertThatThrownBy(() -> underTest.checkIfAnyComponentsIssueSyncInProgress(session, projectKeys, null, null)) + .isInstanceOf(EsIndexSyncInProgressException.class) + .hasFieldOrPropertyWithValue("httpCode", 503) + .hasMessage("Results are temporarily unavailable. Indexing of issues is in progress."); + } + + @Test + public void checkIfAnyComponentsIssueSyncInProgress_does_not_throw_exception_if_all_components_have_need_issue_sync_FALSE() { + underTest.checkIfAnyComponentsIssueSyncInProgress(db.getSession(), Collections.emptyList(), null, null); + ProjectDto projectDto1 = insertProjectWithBranches(false, 0); + ProjectDto projectDto2 = insertProjectWithBranches(false, 0); + underTest.checkIfAnyComponentsIssueSyncInProgress(db.getSession(), Arrays.asList(projectDto1.getKey(), projectDto2.getKey()), null, null); + } + + @Test + public void checkIfAnyComponentsIssueSyncInProgress_throws_exception_if_at_least_one_component_has_need_issue_sync_TRUE() { + ProjectDto projectDto1 = insertProjectWithBranches(false, 0); + ProjectDto projectDto2 = insertProjectWithBranches(true, 0); + + DbSession session = db.getSession(); + List<String> projectKeys = Arrays.asList(projectDto1.getKey(), projectDto2.getKey()); + assertThatThrownBy(() -> underTest.checkIfAnyComponentsIssueSyncInProgress(session, projectKeys, null, null)) + .isInstanceOf(EsIndexSyncInProgressException.class) + .hasFieldOrPropertyWithValue("httpCode", 503) + .hasMessage("Results are temporarily unavailable. Indexing of issues is in progress."); + } + + @Test + public void checkIfAnyComponentsIssueSyncInProgress_single_component() { + ProjectDto projectDto1 = insertProjectWithBranches(true, 0); + ProjectDto projectDto2 = insertProjectWithBranches(false, 0); + + DbSession session = db.getSession(); + List<String> projectKey1 = singletonList(projectDto2.getKey()); + // do nothing when need issue sync false + underTest.checkIfAnyComponentsIssueSyncInProgress(session, projectKey1, null, null); + + List<String> projectKey2 = singletonList(projectDto1.getKey()); + // throws if flag set to TRUE + assertThatThrownBy(() -> underTest.checkIfAnyComponentsIssueSyncInProgress(session, + projectKey2, null, null)) + .isInstanceOf(EsIndexSyncInProgressException.class) + .hasFieldOrPropertyWithValue("httpCode", 503) + .hasMessage("Results are temporarily unavailable. Indexing of issues is in progress."); + } + + @Test + public void checkIfAnyComponentsNeedIssueSync_single_view_subview_or_app() { + ProjectDto projectDto1 = insertProjectWithBranches(true, 0); + + ComponentDto app = db.components().insertPublicApplication(); + ComponentDto view = db.components().insertPrivatePortfolio(); + ComponentDto subview = db.components().insertSubView(view); + + DbSession session = db.getSession(); + List<String> appViewOrSubviewKeys = Arrays.asList(projectDto1.getKey(), app.getDbKey(), view.getDbKey(), subview.getDbKey()); + + // throws if flag set to TRUE + assertThatThrownBy(() -> underTest.checkIfAnyComponentsIssueSyncInProgress(session, + appViewOrSubviewKeys, null, null)) + .isInstanceOf(EsIndexSyncInProgressException.class) + .hasFieldOrPropertyWithValue("httpCode", 503) + .hasMessage("Results are temporarily unavailable. Indexing of issues is in progress."); + } + + @Test + public void checkIfIssueSyncInProgress_throws_exception_if_at_least_one_component_has_need_issue_sync_TRUE() { + insertProjectWithBranches(false, 0); + underTest.checkIfIssueSyncInProgress(db.getSession()); + insertProjectWithBranches(true, 0); + + DbSession session = db.getSession(); + assertThatThrownBy(() -> underTest.checkIfIssueSyncInProgress(session)) + .isInstanceOf(EsIndexSyncInProgressException.class) + .hasFieldOrPropertyWithValue("httpCode", 503) + .hasMessage("Results are temporarily unavailable. Indexing of issues is in progress."); + } + + @Test + public void doProjectNeedIssueSync() { + ProjectDto projectDto1 = insertProjectWithBranches(false, 0); + assertThat(underTest.doProjectNeedIssueSync(db.getSession(), projectDto1.getUuid())).isFalse(); + ProjectDto projectDto2 = insertProjectWithBranches(true, 0); + assertThat(underTest.doProjectNeedIssueSync(db.getSession(), projectDto2.getUuid())).isTrue(); + } + + @Test + public void findProjectUuidsWithIssuesSyncNeed() { + ProjectDto projectDto1 = insertProjectWithBranches(false, 0); + ProjectDto projectDto2 = insertProjectWithBranches(false, 0); + ProjectDto projectDto3 = insertProjectWithBranches(true, 0); + ProjectDto projectDto4 = insertProjectWithBranches(true, 0); + + assertThat(underTest.findProjectUuidsWithIssuesSyncNeed(db.getSession(), + Arrays.asList(projectDto1.getUuid(), projectDto2.getUuid(), projectDto3.getUuid(), projectDto4.getUuid()))) + .containsOnly(projectDto3.getUuid(), projectDto4.getUuid()); + } + + private ProjectDto insertProjectWithBranches(boolean needIssueSync, int numberOfBranches) { ProjectDto projectDto = db.components() .insertPrivateProjectDto(db.getDefaultOrganization(), branchDto -> branchDto.setNeedIssueSync(needIssueSync)); IntStream.range(0, numberOfBranches).forEach( i -> db.components().insertProjectBranch(projectDto, branchDto -> branchDto.setNeedIssueSync(needIssueSync))); + return projectDto; } } |