From e3aff08346215c2b35c0973a97444d0d94b72512 Mon Sep 17 00:00:00 2001 From: Belen Pruvost Date: Wed, 28 Jul 2021 19:42:58 +0200 Subject: [PATCH] SONAR-15139 - Purge Branch properties --- .../org/sonar/db/purge/PurgeCommands.java | 7 ++++ .../java/org/sonar/db/purge/PurgeDao.java | 13 +++++-- .../org/sonar/db/purge/PurgeCommandsTest.java | 33 ++++++++++++++++ .../java/org/sonar/db/purge/PurgeDaoTest.java | 38 ++++++++++++++++++- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java index a4f366c7c98..8eec8a70106 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java @@ -248,6 +248,13 @@ class PurgeCommands { profiler.stop(); } + void deleteOutdatedProperties(String branchUuid) { + profiler.start("deleteOutdatedProperties (properties)"); + purgeMapper.deletePropertiesByComponentUuids(List.of(branchUuid)); + session.commit(); + profiler.stop(); + } + void deleteComponents(String rootUuid) { profiler.start("deleteComponents (projects)"); purgeMapper.deleteComponentsByProjectUuid(rootUuid); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java index ac746986d51..6a02b221547 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Predicate; +import java.util.stream.Collectors; import javax.annotation.Nullable; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.System2; @@ -37,6 +38,7 @@ import org.sonar.db.Dao; import org.sonar.db.DbSession; import org.sonar.db.audit.AuditPersister; import org.sonar.db.audit.model.ComponentNewValue; +import org.sonar.db.component.BranchDto; import org.sonar.db.component.BranchMapper; import org.sonar.db.component.ComponentDto; @@ -54,7 +56,7 @@ public class PurgeDao implements Dao { private final System2 system2; private AuditPersister auditPersister; - public PurgeDao(System2 system2) { + public PurgeDao(System2 system2) { this.system2 = system2; } @@ -192,9 +194,13 @@ public class PurgeDao implements Dao { PurgeCommands purgeCommands = new PurgeCommands(session, profiler, system2); long start = System2.INSTANCE.now(); - session.getMapper(BranchMapper.class).selectByProjectUuid(uuid).stream() + List branchUuids = session.getMapper(BranchMapper.class).selectByProjectUuid(uuid).stream() .filter(branch -> !uuid.equals(branch.getUuid())) - .forEach(branch -> deleteRootComponent(branch.getUuid(), purgeMapper, purgeCommands)); + .map(BranchDto::getUuid) + .collect(Collectors.toList()); + + branchUuids.stream() + .forEach(id -> deleteRootComponent(id, purgeMapper, purgeCommands)); deleteRootComponent(uuid, purgeMapper, purgeCommands); @@ -239,6 +245,7 @@ public class PurgeDao implements Dao { commands.deleteComponentsByMainBranchProjectUuid(rootUuid); commands.deleteProject(rootUuid); commands.deleteUserDismissedMessages(rootUuid); + commands.deleteOutdatedProperties(rootUuid); } /** diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java index 2ae4fc8bf4c..e90f267625f 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java @@ -469,6 +469,23 @@ public class PurgeCommandsTest { assertThat(countAnalysisPropertiesOf(otherAnalysis)).isEqualTo(count); } + @Test + @UseDataProvider("projects") + public void deleteOutdatedProperties_deletes_properties_by_component_uuid(ComponentDto project) { + ComponentDto component = dbTester.components().insertComponent(project); + ComponentDto anotherComponent = dbTester.components().insertPublicProject(); + int count = 4; + IntStream.range(0, count).forEach(i -> { + insertRandomProperty(component); + insertRandomProperty(anotherComponent); + }); + + underTest.deleteOutdatedProperties(component.uuid()); + + assertThat(countPropertiesOf(component)).isZero(); + assertThat(countPropertiesOf(anotherComponent)).isEqualTo(count); + } + @Test @UseDataProvider("projectsAndViews") public void deleteIssues_deletes_all_issues_of_specified_root_component(ComponentDto projectOrView) { @@ -706,6 +723,10 @@ public class PurgeCommandsTest { return dbTester.countSql("select count(1) from analysis_properties where analysis_uuid='" + analysis.getUuid() + "'"); } + private int countPropertiesOf(ComponentDto componentDto) { + return dbTester.countSql("select count(1) from properties where component_uuid='" + componentDto.uuid() + "'"); + } + private int countEventsOf(SnapshotDto analysis) { return dbTester.countSql("select count(1) from events where analysis_uuid='" + analysis.getUuid() + "'"); } @@ -730,6 +751,18 @@ public class PurgeCommandsTest { "CREATED_AT", 1L); } + private void insertRandomProperty(ComponentDto component) { + boolean isEmpty = new Random().nextBoolean(); + dbTester.executeInsert( + "PROPERTIES", + "UUID", newUuid(), + "PROP_KEY", randomAlphabetic(10), + "COMPONENT_UUID", component.uuid(), + "TEXT_VALUE", randomAlphabetic(10), + "IS_EMPTY", isEmpty, + "CREATED_AT", 1L); + } + private int countAnalysesOfRoot(ComponentDto projectOrView) { return dbTester.countSql("select count(1) from snapshots where component_uuid='" + projectOrView.uuid() + "'"); } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java index 375d425eecf..e99f56902fb 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java @@ -24,6 +24,7 @@ import java.io.ByteArrayInputStream; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; @@ -217,12 +218,18 @@ public class PurgeDaoTest { ComponentDto branch1 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH)); db.components().insertSnapshot(branch1, dto -> dto.setCreatedAt(DateUtils.addDays(new Date(), -31).getTime())); - // branch with other components and issues, updated 31 days ago + // branches with other components and issues, updated 31 days ago ComponentDto branch2 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST)); db.components().insertSnapshot(branch2, dto -> dto.setCreatedAt(DateUtils.addDays(new Date(), -31).getTime())); ComponentDto file = db.components().insertComponent(newFileDto(branch2)); db.issues().insert(rule, branch2, file); + ComponentDto branch3 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH)); + db.components().insertSnapshot(branch3, dto -> dto.setCreatedAt(DateUtils.addDays(new Date(), -31).getTime())); + + // properties exist or active and for inactive branch + insertPropertyFor(branch3, branch1); + // analysing branch1 underTest.purge(dbSession, newConfigurationWith30Days(System2.INSTANCE, branch1.uuid(), branch1.getMainBranchProjectUuid()), PurgeListener.EMPTY, new PurgeProfiler()); dbSession.commit(); @@ -230,6 +237,7 @@ public class PurgeDaoTest { // branch1 wasn't deleted since it was being analyzed! assertThat(uuidsIn("components")).containsOnly(project.uuid(), nonMainBranch.uuid(), branch1.uuid()); assertThat(uuidsIn("projects")).containsOnly(project.uuid()); + assertThat(componentUuidsIn("properties")).containsOnly(branch1.uuid()); } @Test @@ -623,6 +631,9 @@ public class PurgeDaoTest { db.components().addProjectBranchToApplicationBranch(dbClient.branchDao().selectByUuid(dbSession, appBranch.uuid()).get(), projectBranch); db.components().addProjectBranchToApplicationBranch(dbClient.branchDao().selectByUuid(dbSession, otherAppBranch.uuid()).get(), projectBranch); + // properties exist or active and for inactive branch + insertPropertyFor(appBranch, otherAppBranch); + underTest.deleteBranch(dbSession, appBranch.uuid()); dbSession.commit(); @@ -633,6 +644,8 @@ public class PurgeDaoTest { assertThat(uuidsIn("project_measures")).containsOnly(appMeasure.getUuid(), otherAppMeasure.getUuid(), otherAppBranchMeasure.getUuid()); assertThat(uuidsIn("app_projects", "application_uuid")).containsOnly(app.uuid(), otherApp.uuid()); assertThat(uuidsIn("app_branch_project_branch", "application_branch_uuid")).containsOnly(otherAppBranch.uuid()); + assertThat(componentUuidsIn("properties")).containsOnly(otherAppBranch.uuid()); + } @Test @@ -1053,8 +1066,18 @@ public class PurgeDaoTest { int projectEntryCount = db.countRowsOfTable("components"); int issueCount = db.countRowsOfTable("issues"); int branchCount = db.countRowsOfTable("project_branches"); + Collection anotherLivingProjectBranches = db.getDbClient().branchDao() + .selectByComponent(db.getSession(), anotherLivingProject); + insertPropertyFor(anotherLivingProjectBranches); + + assertThat(db.countRowsOfTable("properties")).isEqualTo(anotherLivingProjectBranches.size()); ComponentDto projectToDelete = insertProjectWithBranchAndRelatedData(); + Collection projectToDeleteBranches = db.getDbClient().branchDao() + .selectByComponent(db.getSession(), projectToDelete); + insertPropertyFor(projectToDeleteBranches); + + assertThat(db.countRowsOfTable("properties")).isEqualTo(anotherLivingProjectBranches.size() + projectToDeleteBranches.size()); assertThat(db.countRowsOfTable("components")).isGreaterThan(projectEntryCount); assertThat(db.countRowsOfTable("issues")).isGreaterThan(issueCount); assertThat(db.countRowsOfTable("project_branches")).isGreaterThan(branchCount); @@ -1065,6 +1088,7 @@ public class PurgeDaoTest { assertThat(db.countRowsOfTable("components")).isEqualTo(projectEntryCount); assertThat(db.countRowsOfTable("issues")).isEqualTo(issueCount); assertThat(db.countRowsOfTable("project_branches")).isEqualTo(branchCount); + assertThat(db.countRowsOfTable("properties")).isEqualTo(anotherLivingProjectBranches.size()); } @Test @@ -1639,6 +1663,14 @@ public class PurgeDaoTest { componentDto.name(), null)); } + private void insertPropertyFor(Collection branches) { + branches.stream().forEach(branchDto -> db.properties().insertProperty(new PropertyDto() + .setKey(randomAlphabetic(3)) + .setValue(randomAlphabetic(3)) + .setComponentUuid(branchDto.getUuid()), + branchDto.getKey(), null)); + } + private Stream getComponentUuidsOfMeasures() { return db.select("select component_uuid as \"COMPONENT_UUID\" from project_measures").stream() .map(row -> (String) row.get("COMPONENT_UUID")); @@ -1736,6 +1768,10 @@ public class PurgeDaoTest { return uuidsIn(tableName, "uuid"); } + private Stream componentUuidsIn(String tableName) { + return uuidsIn(tableName, "component_uuid"); + } + private Stream taskUuidsIn(String tableName) { return uuidsIn(tableName, "task_uuid"); } -- 2.39.5