From 94ae3b76e8e25adb3d7f266de45bce298e971a1f Mon Sep 17 00:00:00 2001 From: Jacek Date: Tue, 9 Jun 2020 11:32:36 +0200 Subject: [PATCH] SONAR-13398 fail with 503 api/issues/tags WS if needIssueSync is set to true --- .../index/IssueIndexSyncProgressChecker.java | 7 +++++- .../IssueIndexSyncProgressCheckerTest.java | 12 +++++----- .../sonar/server/hotspot/ws/SearchAction.java | 2 +- .../sonar/server/issue/ws/SearchAction.java | 2 +- .../org/sonar/server/issue/ws/TagsAction.java | 22 ++++++++++++++++--- .../server/hotspot/ws/SearchActionTest.java | 6 ++--- .../sonar/server/issue/ws/TagsActionTest.java | 10 ++++++++- 7 files changed, 45 insertions(+), 16 deletions(-) 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 6e9ea790226..5c6aefe3a90 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 @@ -21,6 +21,7 @@ package org.sonar.server.issue.index; import com.google.common.collect.Sets; import java.util.Collection; +import java.util.Collections; import java.util.List; import javax.annotation.Nullable; import org.sonar.db.DbClient; @@ -40,7 +41,7 @@ public class IssueIndexSyncProgressChecker { return new IssueSyncProgress(completed, total); } - public void checkIfAnyComponentsIssueSyncInProgress(DbSession dbSession, List componentKeys, @Nullable String branch, + public void checkIfAnyComponentsNeedIssueSync(DbSession dbSession, List componentKeys, @Nullable String branch, @Nullable String pullRequest) { boolean needIssueSync = dbClient.branchDao().doAnyOfComponentsNeedIssueSync(dbSession, componentKeys, branch, pullRequest); if (needIssueSync) { @@ -49,6 +50,10 @@ public class IssueIndexSyncProgressChecker { } } + public void checkIfComponentNeedIssueSync(DbSession dbSession, String componentKey) { + checkIfAnyComponentsNeedIssueSync(dbSession, Collections.singletonList(componentKey), null, null); + } + /** * Checks if issue index sync is in progress, if it is, method throws exception org.sonar.server.es.EsIndexSyncInProgressException */ 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 d036d47eea0..d41cf3188da 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 @@ -121,7 +121,7 @@ public class IssueIndexSyncProgressCheckerTest { ProjectDto projectDto2 = insertProjectWithBranches(true, 0); DbSession session = db.getSession(); List projectKeys = Arrays.asList(projectDto1.getKey(), projectDto2.getKey()); - assertThatThrownBy(() -> underTest.checkIfAnyComponentsIssueSyncInProgress(session, projectKeys, null, null)) + assertThatThrownBy(() -> underTest.checkIfAnyComponentsNeedIssueSync(session, projectKeys, null, null)) .isInstanceOf(EsIndexSyncInProgressException.class) .hasFieldOrPropertyWithValue("httpCode", 503) .hasMessage("Results are temporarily unavailable. Indexing of issues is in progress."); @@ -129,10 +129,10 @@ public class IssueIndexSyncProgressCheckerTest { @Test public void checkIfAnyComponentsIssueSyncInProgress_does_not_throw_exception_if_all_components_have_need_issue_sync_FALSE() { - underTest.checkIfAnyComponentsIssueSyncInProgress(db.getSession(), Collections.emptyList(), null, null); + underTest.checkIfAnyComponentsNeedIssueSync(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); + underTest.checkIfAnyComponentsNeedIssueSync(db.getSession(), Arrays.asList(projectDto1.getKey(), projectDto2.getKey()), null, null); } @Test @@ -142,7 +142,7 @@ public class IssueIndexSyncProgressCheckerTest { DbSession session = db.getSession(); List projectKeys = Arrays.asList(projectDto1.getKey(), projectDto2.getKey()); - assertThatThrownBy(() -> underTest.checkIfAnyComponentsIssueSyncInProgress(session, projectKeys, null, null)) + assertThatThrownBy(() -> underTest.checkIfAnyComponentsNeedIssueSync(session, projectKeys, null, null)) .isInstanceOf(EsIndexSyncInProgressException.class) .hasFieldOrPropertyWithValue("httpCode", 503) .hasMessage("Results are temporarily unavailable. Indexing of issues is in progress."); @@ -156,11 +156,11 @@ public class IssueIndexSyncProgressCheckerTest { DbSession session = db.getSession(); List projectKey1 = singletonList(projectDto2.getKey()); // do nothing when need issue sync false - underTest.checkIfAnyComponentsIssueSyncInProgress(session, projectKey1, null, null); + underTest.checkIfAnyComponentsNeedIssueSync(session, projectKey1, null, null); List projectKey2 = singletonList(projectDto1.getKey()); // throws if flag set to TRUE - assertThatThrownBy(() -> underTest.checkIfAnyComponentsIssueSyncInProgress(session, + assertThatThrownBy(() -> underTest.checkIfAnyComponentsNeedIssueSync(session, projectKey2, null, null)) .isInstanceOf(EsIndexSyncInProgressException.class) .hasFieldOrPropertyWithValue("httpCode", 503) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java index 58f1cadc05d..4bc64bce33d 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java @@ -186,7 +186,7 @@ public class SearchAction implements HotspotsWsAction { if (projectKey.isPresent()) { String branch = wsRequest.getBranch().orElse(null); String pullRequest = wsRequest.getPullRequest().orElse(null); - issueIndexSyncProgressChecker.checkIfAnyComponentsIssueSyncInProgress(dbSession, singletonList(projectKey.get()), branch, pullRequest); + issueIndexSyncProgressChecker.checkIfAnyComponentsNeedIssueSync(dbSession, singletonList(projectKey.get()), branch, pullRequest); } else { // component keys not provided - asking for global issueIndexSyncProgressChecker.checkIfIssueSyncInProgress(dbSession); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java index aa4ab9338ec..f6d7cdae718 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java @@ -546,7 +546,7 @@ public class SearchAction implements IssuesWsAction { if (components != null && !components.isEmpty()) { String branch = searchRequest.getBranch(); String pullRequest = searchRequest.getPullRequest(); - issueIndexSyncProgressChecker.checkIfAnyComponentsIssueSyncInProgress(dbSession, components, branch, pullRequest); + issueIndexSyncProgressChecker.checkIfAnyComponentsNeedIssueSync(dbSession, components, branch, pullRequest); } else { // component keys not provided - asking for global issueIndexSyncProgressChecker.checkIfIssueSyncInProgress(dbSession); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/TagsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/TagsAction.java index dcd8c9d47c4..4d04218a5db 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/TagsAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/TagsAction.java @@ -37,6 +37,7 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.issue.index.IssueIndex; +import org.sonar.server.issue.index.IssueIndexSyncProgressChecker; import org.sonar.server.issue.index.IssueQuery; import org.sonarqube.ws.Issues; @@ -58,11 +59,15 @@ public class TagsAction implements IssuesWsAction { private static final String PARAM_PROJECT = "project"; private final IssueIndex issueIndex; + private final IssueIndexSyncProgressChecker issueIndexSyncProgressChecker; private final DbClient dbClient; private final ComponentFinder componentFinder; - public TagsAction(IssueIndex issueIndex, DbClient dbClient, ComponentFinder componentFinder) { + public TagsAction(IssueIndex issueIndex, + IssueIndexSyncProgressChecker issueIndexSyncProgressChecker, DbClient dbClient, + ComponentFinder componentFinder) { this.issueIndex = issueIndex; + this.issueIndexSyncProgressChecker = issueIndexSyncProgressChecker; this.dbClient = dbClient; this.componentFinder = componentFinder; } @@ -93,8 +98,11 @@ public class TagsAction implements IssuesWsAction { @Override public void handle(Request request, Response response) throws Exception { try (DbSession dbSession = dbClient.openSession(false)) { - Optional organization = getOrganization(dbSession, request.param(PARAM_ORGANIZATION)); - Optional project = getProject(dbSession, organization, request.param(PARAM_PROJECT)); + String projectKey = request.param(PARAM_PROJECT); + String organizatioKey = request.param(PARAM_ORGANIZATION); + checkIfAnyComponentsNeedIssueSync(dbSession, projectKey); + Optional organization = getOrganization(dbSession, organizatioKey); + Optional project = getProject(dbSession, organization, projectKey); List tags = searchTags(organization, project, request); Issues.TagsResponse.Builder tagsResponseBuilder = Issues.TagsResponse.newBuilder(); tags.forEach(tagsResponseBuilder::addTags); @@ -117,6 +125,14 @@ public class TagsAction implements IssuesWsAction { return Optional.of(project); } + private void checkIfAnyComponentsNeedIssueSync(DbSession session, @Nullable String projectKey) { + if (projectKey != null) { + issueIndexSyncProgressChecker.checkIfComponentNeedIssueSync(session, projectKey); + } else { + issueIndexSyncProgressChecker.checkIfIssueSyncInProgress(session); + } + } + private List searchTags(Optional organization, Optional project, Request request) { IssueQuery.Builder issueQueryBuilder = IssueQuery.builder() .types(ISSUE_TYPE_NAMES); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/SearchActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/SearchActionTest.java index 21160473bcb..f41016a90af 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/SearchActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/SearchActionTest.java @@ -671,9 +671,9 @@ public class SearchActionTest { .extracting(SearchWsResponse.Hotspot::getKey) .containsExactlyInAnyOrder(Arrays.stream(hotspotPR).map(IssueDto::getKey).toArray(String[]::new)); - verify(issueIndexSyncProgressChecker).checkIfAnyComponentsIssueSyncInProgress(any(), argThat(arg -> arg.contains(project.getKey())), isNull(), isNull()); - verify(issueIndexSyncProgressChecker).checkIfAnyComponentsIssueSyncInProgress(any(), argThat(arg -> arg.contains(project.getKey())), eq(branch.getBranch()), isNull()); - verify(issueIndexSyncProgressChecker).checkIfAnyComponentsIssueSyncInProgress(any(), argThat(arg -> arg.contains(project.getKey())), isNull(), eq(branch.getPullRequest())); + verify(issueIndexSyncProgressChecker).checkIfAnyComponentsNeedIssueSync(any(), argThat(arg -> arg.contains(project.getKey())), isNull(), isNull()); + verify(issueIndexSyncProgressChecker).checkIfAnyComponentsNeedIssueSync(any(), argThat(arg -> arg.contains(project.getKey())), eq(branch.getBranch()), isNull()); + verify(issueIndexSyncProgressChecker).checkIfAnyComponentsNeedIssueSync(any(), argThat(arg -> arg.contains(project.getKey())), isNull(), eq(branch.getPullRequest())); } @Test diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/TagsActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/TagsActionTest.java index 3e68a498cf7..db956239458 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/TagsActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/TagsActionTest.java @@ -36,6 +36,7 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.es.EsTester; import org.sonar.server.issue.index.IssueIndex; +import org.sonar.server.issue.index.IssueIndexSyncProgressChecker; import org.sonar.server.issue.index.IssueIndexer; import org.sonar.server.issue.index.IssueIteratorFactory; import org.sonar.server.permission.index.PermissionIndexerTester; @@ -52,6 +53,10 @@ import static java.util.Collections.emptySet; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newProjectCopy; @@ -69,12 +74,13 @@ public class TagsActionTest { public ExpectedException expectedException = ExpectedException.none(); private IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSession, new WebAuthorizationTypeSupport(userSession)); + private IssueIndexSyncProgressChecker issueIndexSyncProgressChecker = mock(IssueIndexSyncProgressChecker.class); private IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), null); private ViewIndexer viewIndexer = new ViewIndexer(db.getDbClient(), es.client()); private PermissionIndexerTester permissionIndexer = new PermissionIndexerTester(es, issueIndexer); private ResourceTypesRule resourceTypes = new ResourceTypesRule().setRootQualifiers(PROJECT); - private WsActionTester ws = new WsActionTester(new TagsAction(issueIndex, db.getDbClient(), new ComponentFinder(db.getDbClient(), resourceTypes))); + private WsActionTester ws = new WsActionTester(new TagsAction(issueIndex, issueIndexSyncProgressChecker, db.getDbClient(), new ComponentFinder(db.getDbClient(), resourceTypes))); @Test public void search_tags() { @@ -88,6 +94,7 @@ public class TagsActionTest { TagsResponse result = ws.newRequest().executeProtobuf(TagsResponse.class); assertThat(result.getTagsList()).containsExactly("tag1", "tag2", "tag3", "tag4", "tag5"); + verify(issueIndexSyncProgressChecker).checkIfIssueSyncInProgress(any()); } @Test @@ -187,6 +194,7 @@ public class TagsActionTest { assertThat(tagListOf(ws.newRequest() .setParam("organization", organization.getKey()) .setParam("project", project1.getKey()))).containsExactly("tag1"); + verify(issueIndexSyncProgressChecker).checkIfComponentNeedIssueSync(any(), eq(project1.getKey())); } @Test -- 2.39.5