From beb0a7404e0cf29999716baef279c38460d7d53a Mon Sep 17 00:00:00 2001 From: Jacek Date: Fri, 19 Jun 2020 14:49:21 +0200 Subject: [PATCH] SONAR-13398 Throw ES exception in case component is a portfolio, subview or app --- .../org/sonar/db/component/BranchDao.java | 2 +- .../org/sonar/db/component/ComponentDao.java | 13 +++++++ .../sonar/db/component/ComponentMapper.java | 2 ++ .../sonar/db/component/ComponentMapper.xml | 34 +++++++++++++++---- .../sonar/db/component/ComponentDaoTest.java | 26 ++++++++++++++ .../index/IssueIndexSyncProgressChecker.java | 14 +++++++- .../IssueIndexSyncProgressCheckerTest.java | 17 ++++------ 7 files changed, 89 insertions(+), 19 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/BranchDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/BranchDao.java index b55ce5a0b75..0898737cec8 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/BranchDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/BranchDao.java @@ -160,7 +160,7 @@ public class BranchDao implements Dao { if (!components.isEmpty()) { List result = new LinkedList<>(); return executeLargeInputs(components, input -> { - boolean groupNeedIssueSync = mapper(session).doAnyOfComponentsNeedIssueSync(components) > 0; + boolean groupNeedIssueSync = mapper(session).doAnyOfComponentsNeedIssueSync(input) > 0; result.add(groupNeedIssueSync); return result; }).stream() diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java index d95733ac75c..e4426e519b7 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Optional; @@ -395,4 +396,16 @@ public class ComponentDao implements Dao { return Optional.ofNullable(mapper(dbSession).selectByAlmIdAndAlmRepositoryId(almId, almRepositoryId)); } + public boolean existAnyOfComponentsWithQualifiers(DbSession session, Collection componentKeys, Set qualifiers) { + if (!componentKeys.isEmpty()) { + List result = new LinkedList<>(); + return executeLargeInputs(componentKeys, input -> { + boolean groupNeedIssueSync = mapper(session).checkIfAnyOfComponentsWithQualifiers(input, qualifiers) > 0; + result.add(groupNeedIssueSync); + return result; + }).stream().anyMatch(b -> b); + } + return false; + } + } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java index 32f99628b4b..3081461ed4c 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java @@ -157,4 +157,6 @@ public interface ComponentMapper { List selectPrivateProjectsWithNcloc(@Param("organizationUuid") String organizationUuid); List selectEnabledComponentsWithModuleUuidFromProjectKey(String projectKey); + + short checkIfAnyOfComponentsWithQualifiers(@Param("componentKeys") Collection componentKeys, @Param("qualifiers") Set qualifiers); } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml index f6513e87ee6..0254590f60a 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml @@ -740,14 +740,34 @@ where m.name = 'ncloc' and b.key_type = 'BRANCH' - and b.branch_type = 'BRANCH' - and p.enabled = ${_true} - and p.private = ${_true} - and p.scope = 'PRJ' - and p.qualifier = 'TRK' - and p.copy_component_uuid is null - and p.organization_uuid = #{organizationUuid, jdbcType=VARCHAR} + and b.branch_type = 'BRANCH' + and p.enabled = ${_true} + and p.private = ${_true} + and p.scope = 'PRJ' + and p.qualifier = 'TRK' + and p.copy_component_uuid is null + and p.organization_uuid = #{organizationUuid, jdbcType=VARCHAR} group by p.kee, p.name order by ncloc desc + + diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java index eb93250b8d0..a3d473b0c05 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java @@ -56,6 +56,7 @@ import org.sonar.db.source.FileSourceDto; import static com.google.common.collect.ImmutableSet.of; import static com.google.common.collect.Sets.newHashSet; import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static java.util.Collections.singletonList; @@ -67,9 +68,12 @@ import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.tuple; import static org.sonar.api.resources.Qualifiers.APP; import static org.sonar.api.resources.Qualifiers.PROJECT; +import static org.sonar.api.resources.Qualifiers.SUBVIEW; +import static org.sonar.api.resources.Qualifiers.VIEW; import static org.sonar.api.utils.DateUtils.parseDate; import static org.sonar.db.component.BranchType.BRANCH; import static org.sonar.db.component.BranchType.PULL_REQUEST; +import static org.sonar.db.component.ComponentTesting.newApplication; import static org.sonar.db.component.ComponentTesting.newBranchDto; import static org.sonar.db.component.ComponentTesting.newDirectory; import static org.sonar.db.component.ComponentTesting.newFileDto; @@ -1886,6 +1890,28 @@ public class ComponentDaoTest { assertThat(result).extracting(ProjectNclocDistributionDto::getNcloc).containsExactly(30L, 10L); } + @Test + public void existAnyOfComponentsWithQualifiers() { + ComponentDto projectDto = db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization())); + + ComponentDto view = db.components().insertComponent(newView(db.getDefaultOrganization())); + ComponentDto subview = db.components().insertComponent(newSubView(view)); + + ComponentDto app = db.components().insertComponent(newApplication(db.getDefaultOrganization())); + + assertThat(underTest.existAnyOfComponentsWithQualifiers(db.getSession(), emptyList(), newHashSet(APP, VIEW, SUBVIEW))).isFalse(); + assertThat(underTest.existAnyOfComponentsWithQualifiers(db.getSession(), singletonList("not-existing-component"), newHashSet(APP, VIEW, SUBVIEW))).isFalse(); + assertThat(underTest.existAnyOfComponentsWithQualifiers(db.getSession(), singletonList(projectDto.getKey()), newHashSet(APP, VIEW, SUBVIEW))).isFalse(); + + assertThat(underTest.existAnyOfComponentsWithQualifiers(db.getSession(), singletonList(projectDto.getKey()), newHashSet(PROJECT))).isTrue(); + + assertThat(underTest.existAnyOfComponentsWithQualifiers(db.getSession(), singletonList(view.getKey()), newHashSet(APP, VIEW, SUBVIEW))).isTrue(); + assertThat(underTest.existAnyOfComponentsWithQualifiers(db.getSession(), singletonList(subview.getKey()), newHashSet(APP, VIEW, SUBVIEW))).isTrue(); + assertThat(underTest.existAnyOfComponentsWithQualifiers(db.getSession(), singletonList(app.getKey()), newHashSet(APP, VIEW, SUBVIEW))).isTrue(); + + assertThat(underTest.existAnyOfComponentsWithQualifiers(db.getSession(), newHashSet(projectDto.getKey(), view.getKey()), newHashSet(APP, VIEW, SUBVIEW))).isTrue(); + } + private boolean privateFlagOfUuid(String uuid) { return underTest.selectByUuid(db.getSession(), uuid).get().isPrivate(); } 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 04dddb7da78..3f72e04166a 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 @@ -19,6 +19,7 @@ */ package org.sonar.server.issue.index; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import java.util.Collection; import java.util.Collections; @@ -27,7 +28,12 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.server.es.EsIndexSyncInProgressException; +import static org.sonar.api.resources.Qualifiers.APP; +import static org.sonar.api.resources.Qualifiers.SUBVIEW; +import static org.sonar.api.resources.Qualifiers.VIEW; + public class IssueIndexSyncProgressChecker { + private static final ImmutableSet APP_VIEW_OR_SUBVIEW = ImmutableSet.builder().add(VIEW, SUBVIEW, APP).build(); private final DbClient dbClient; public IssueIndexSyncProgressChecker(DbClient dbClient) { @@ -43,7 +49,13 @@ public class IssueIndexSyncProgressChecker { } public void checkIfAnyComponentsNeedIssueSync(DbSession dbSession, List componentKeys) { - boolean needIssueSync = dbClient.branchDao().doAnyOfComponentsNeedIssueSync(dbSession, componentKeys); + boolean isAppOrViewOrSubview = dbClient.componentDao().existAnyOfComponentsWithQualifiers(dbSession, componentKeys, APP_VIEW_OR_SUBVIEW); + boolean needIssueSync; + if (isAppOrViewOrSubview) { + needIssueSync = dbClient.branchDao().hasAnyBranchWhereNeedIssueSync(dbSession, true); + } else { + needIssueSync = dbClient.branchDao().doAnyOfComponentsNeedIssueSync(dbSession, componentKeys); + } if (needIssueSync) { throw new EsIndexSyncInProgressException(IssueIndexDefinition.TYPE_ISSUE.getMainType(), "Results are temporarily unavailable. Indexing of issues is in progress."); 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 254d2f58ba5..06f073d3564 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 @@ -40,7 +40,6 @@ 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; import static org.sonar.db.ce.CeActivityDto.Status.FAILED; @@ -205,7 +204,7 @@ public class IssueIndexSyncProgressCheckerTest { } @Test - public void checkIfAnyComponentsIssueSyncInProgress_throws_exception_if_all_components_have_need_issue_sync_TRUE() { + public void checkIfAnyComponentsNeedIssueSync_throws_exception_if_all_components_have_need_issue_sync_TRUE() { ProjectDto projectDto1 = insertProjectWithBranches(true, 0); ProjectDto projectDto2 = insertProjectWithBranches(true, 0); DbSession session = db.getSession(); @@ -217,7 +216,7 @@ public class IssueIndexSyncProgressCheckerTest { } @Test - public void checkIfAnyComponentsIssueSyncInProgress_does_not_throw_exception_if_all_components_have_need_issue_sync_FALSE() { + public void checkIfAnyComponentsNeedIssueSync_does_not_throw_exception_if_all_components_have_need_issue_sync_FALSE() { underTest.checkIfAnyComponentsNeedIssueSync(db.getSession(), Collections.emptyList()); ProjectDto projectDto1 = insertProjectWithBranches(false, 0); ProjectDto projectDto2 = insertProjectWithBranches(false, 0); @@ -225,7 +224,7 @@ public class IssueIndexSyncProgressCheckerTest { } @Test - public void checkIfAnyComponentsIssueSyncInProgress_throws_exception_if_at_least_one_component_has_need_issue_sync_TRUE() { + public void checkIfAnyComponentsNeedIssueSync_throws_exception_if_at_least_one_component_has_need_issue_sync_TRUE() { ProjectDto projectDto1 = insertProjectWithBranches(false, 0); ProjectDto projectDto2 = insertProjectWithBranches(true, 0); @@ -238,19 +237,17 @@ public class IssueIndexSyncProgressCheckerTest { } @Test - public void checkIfAnyComponentsIssueSyncInProgress_single_component() { + public void checkIfComponentNeedIssueSync_single_component() { ProjectDto projectDto1 = insertProjectWithBranches(true, 0); ProjectDto projectDto2 = insertProjectWithBranches(false, 0); DbSession session = db.getSession(); - List projectKey1 = singletonList(projectDto2.getKey()); // do nothing when need issue sync false - underTest.checkIfAnyComponentsNeedIssueSync(session, projectKey1); + underTest.checkIfComponentNeedIssueSync(session, projectDto2.getKey()); - List projectKey2 = singletonList(projectDto1.getKey()); // throws if flag set to TRUE - assertThatThrownBy(() -> underTest.checkIfAnyComponentsNeedIssueSync(session, - projectKey2)) + assertThatThrownBy(() -> underTest.checkIfComponentNeedIssueSync(session, + projectDto1.getKey())) .isInstanceOf(EsIndexSyncInProgressException.class) .hasFieldOrPropertyWithValue("httpCode", 503) .hasMessage("Results are temporarily unavailable. Indexing of issues is in progress."); -- 2.39.5