From 7de252ea61bdfc2cb33f74f04aa781d0ad773183 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Mon, 29 Sep 2014 11:43:58 +0200 Subject: [PATCH] SONAR-5624 clean analysis report tasks to pending when server is starting and truncate when upgrading --- .../server/batch/UploadReportAction.java | 20 +++--- .../AnalysisReportTasksCleaner.java | 62 +++++++++++++++++ .../computation/ComputationService.java | 16 ++++- .../computation/db/AnalysisReportDao.java | 33 +++++++-- .../server/platform/ServerComponents.java | 2 + .../batch/UploadReportActionMediumTest.java | 27 ++++++++ .../AnalysisReportTasksCleanerTest.java | 67 +++++++++++++++++++ .../computation/ComputationServiceTest.java | 59 ++++++++++++++++ .../computation/db/AnalysisReportDaoTest.java | 52 +++++++++++++- .../any-analysis-reports.xml | 26 +++++++ .../AnalysisReportDaoTest/insert-result.xml | 8 +++ .../db/AnalysisReportDaoTest/select.xml | 26 +++++++ .../AnalysisReportDaoTest/truncate-result.xml | 3 + .../update-all-to-status-pending-result.xml | 46 +++++++++++++ .../update-all-to-status-pending.xml | 26 +++++++ .../computation/db/AnalysisReportDto.java | 2 +- .../computation/db/AnalysisReportMapper.java | 16 +++++ .../computation/db/AnalysisReportMapper.xml | 25 ++++++- 18 files changed, 496 insertions(+), 20 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTasksCleaner.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTasksCleanerTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/truncate-result.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java index 3c0d2f90b1b..15290fb9cfb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java @@ -76,19 +76,19 @@ public class UploadReportAction implements RequestHandler { public void handle(Request request, Response response) throws Exception { UserSession.get().checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION); - // Switch Issue search - if (settings.getString("sonar.issues.use_es_backend") != null) { - String projectKey = request.mandatoryParam(PARAM_PROJECT); + String projectKey = request.mandatoryParam(PARAM_PROJECT); - DbSession session = dbClient.openSession(false); - try { - dbClient.componentDao().getAuthorizedComponentByKey(projectKey, session); - computationService.create(projectKey); + DbSession session = dbClient.openSession(false); + try { + dbClient.componentDao().getAuthorizedComponentByKey(projectKey, session); + computationService.create(projectKey); - } finally { - MyBatis.closeQuietly(session); - } + } finally { + MyBatis.closeQuietly(session); + } + // Switch Issue search + if (settings.getString("sonar.issues.use_es_backend") != null) { // Synchronization of lot of data can only be done with a batch session for the moment session = dbClient.openSession(true); try { diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTasksCleaner.java b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTasksCleaner.java new file mode 100644 index 00000000000..77929d47b98 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTasksCleaner.java @@ -0,0 +1,62 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.computation; + +import org.picocontainer.Startable; +import org.sonar.api.ServerComponent; +import org.sonar.api.platform.ServerUpgradeStatus; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.server.computation.db.AnalysisReportDao; +import org.sonar.server.db.DbClient; + +public class AnalysisReportTasksCleaner implements Startable, ServerComponent { + private final ServerUpgradeStatus serverUpgradeStatus; + private final DbClient dbClient; + + public AnalysisReportTasksCleaner(ServerUpgradeStatus serverUpgradeStatus, DbClient dbClient) { + this.serverUpgradeStatus = serverUpgradeStatus; + this.dbClient = dbClient; + } + + @Override + public void start() { + DbSession session = dbClient.openSession(false); + AnalysisReportDao dao = dbClient.analysisReportDao(); + + try { + if (serverUpgradeStatus.isUpgraded()) { + dao.cleanWithTruncate(session); + } else { + dao.cleanWithUpdateAllToPendingStatus(session); + } + + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + @Override + public void stop() { + // do nothing + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java index 37cd3abc274..74112ddd24e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java @@ -23,9 +23,12 @@ package org.sonar.server.computation; import org.sonar.api.ServerComponent; import org.sonar.core.computation.db.AnalysisReportDto; import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; import org.sonar.server.computation.db.AnalysisReportDao; import org.sonar.server.db.DbClient; +import java.util.List; + import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING; /** @@ -50,7 +53,18 @@ public class ComputationService implements ServerComponent { dao.insert(session, report); session.commit(); } finally { - session.close(); + MyBatis.closeQuietly(session); + } + } + + public List findByProjectKey(String projectKey) { + AnalysisReportDao dao = dbClient.analysisReportDao(); + + DbSession session = dbClient.openSession(false); + try { + return dao.findByProjectKey(session, projectKey); + } finally { + MyBatis.closeQuietly(session); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/db/AnalysisReportDao.java b/server/sonar-server/src/main/java/org/sonar/server/computation/db/AnalysisReportDao.java index 88fa780a4ea..6b26191e1fd 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/db/AnalysisReportDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/db/AnalysisReportDao.java @@ -23,29 +23,51 @@ package org.sonar.server.computation.db; import com.google.common.annotations.VisibleForTesting; import org.sonar.api.utils.System2; import org.sonar.core.computation.db.AnalysisReportDto; +import org.sonar.core.computation.db.AnalysisReportDto.Status; import org.sonar.core.computation.db.AnalysisReportMapper; import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.DbSession; import org.sonar.server.db.BaseDao; import java.util.Date; +import java.util.List; import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; - public class AnalysisReportDao extends BaseDao implements DaoComponent { + private System2 system2; + public AnalysisReportDao() { this(System2.INSTANCE); } @VisibleForTesting - public AnalysisReportDao(System2 system) { - super(AnalysisReportMapper.class, system); + public AnalysisReportDao(System2 system2) { + super(AnalysisReportMapper.class, system2); + this.system2 = system2; + } + + /** + * startup task use only + */ + public void cleanWithUpdateAllToPendingStatus(DbSession session) { + mapper(session).cleanWithUpdateAllToPendingStatus(Status.PENDING, new Date(system2.now())); + } + + /** + * startup task use only + */ + public void cleanWithTruncate(DbSession session) { + mapper(session).cleanWithTruncate(); + } + + public List findByProjectKey(DbSession session, String projectKey) { + List analysisReports = mapper(session).selectByProjectKey(projectKey); + return analysisReports; } @Override - protected AnalysisReportDto doGetNullableByKey(DbSession session, String key) { + protected AnalysisReportDto doGetNullableByKey(DbSession session, String projectKey) { throw new UnsupportedOperationException(); } @@ -56,7 +78,6 @@ public class AnalysisReportDao extends BaseDao analysisReports = db.analysisReportDao().findByProjectKey(session, projectKey); + AnalysisReportDto analysisReport = analysisReports.get(0); + + assertThat(analysisReports).hasSize(1); + assertThat(analysisReport.getProjectKey()).isEqualTo(projectKey); + assertThat(analysisReport.getStatus()).isEqualTo(PENDING); + } @Test(expected = ForbiddenException.class) public void fail_without_global_scan_permission() throws Exception { diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTasksCleanerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTasksCleanerTest.java new file mode 100644 index 00000000000..e9ee75f1638 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTasksCleanerTest.java @@ -0,0 +1,67 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.computation; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.platform.ServerUpgradeStatus; +import org.sonar.core.persistence.DbSession; +import org.sonar.server.computation.db.AnalysisReportDao; +import org.sonar.server.db.DbClient; + +import static org.mockito.Mockito.*; + +public class AnalysisReportTasksCleanerTest { + + AnalysisReportTasksCleaner sut; + ServerUpgradeStatus serverUpgradeStatus; + DbClient dbClient; + AnalysisReportDao analysisReportDao; + DbSession session; + + @Before + public void before() { + analysisReportDao = mock(AnalysisReportDao.class); + serverUpgradeStatus = mock(ServerUpgradeStatus.class); + dbClient = mock(DbClient.class); + session = mock(DbSession.class); + + when(dbClient.analysisReportDao()).thenReturn(analysisReportDao); + when(dbClient.openSession(false)).thenReturn(session); + + sut = new AnalysisReportTasksCleaner(serverUpgradeStatus, dbClient); + } + + @Test + public void start_must_call_dao_clean_update_to_pending_by_default() { + sut.start(); + verify(analysisReportDao).cleanWithUpdateAllToPendingStatus(any(DbSession.class)); + sut.stop(); + } + + @Test + public void start_must_call_dao_truncate_when_upgrading() { + when(serverUpgradeStatus.isUpgraded()).thenReturn(Boolean.TRUE); + sut.start(); + verify(analysisReportDao).cleanWithTruncate(any(DbSession.class)); + sut.stop(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java new file mode 100644 index 00000000000..cacc48e9483 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java @@ -0,0 +1,59 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.computation; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.core.computation.db.AnalysisReportDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.server.computation.db.AnalysisReportDao; +import org.sonar.server.db.DbClient; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class ComputationServiceTest { + + ComputationService sut; + DbClient dbClient; + AnalysisReportDao analysisReportDao; + DbSession session; + + @Before + public void before() { + analysisReportDao = mock(AnalysisReportDao.class); + dbClient = mock(DbClient.class); + session = mock(DbSession.class); + + when(dbClient.analysisReportDao()).thenReturn(analysisReportDao); + when(dbClient.openSession(false)).thenReturn(session); + + sut = new ComputationService(dbClient); + } + + @Test + public void create_must_call_dao_insert() throws Exception { + sut.create("ANY-KEY"); + verify(analysisReportDao).insert(any(DbSession.class), any(AnalysisReportDto.class)); + } +} \ No newline at end of file diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java index cc07f14d388..d442b589b8a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java @@ -30,6 +30,9 @@ import org.sonar.core.computation.db.AnalysisReportDto; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.TestDatabase; +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING; @@ -55,7 +58,7 @@ public class AnalysisReportDaoTest { } @Test - public void insert() { + public void insert_multiple_reports() { when(system2.now()).thenReturn(DateUtils.parseDate("2014-09-26").getTime()); AnalysisReportDto report = new AnalysisReportDto() @@ -66,8 +69,55 @@ public class AnalysisReportDaoTest { .setUpdatedAt(DateUtils.parseDate("2014-09-25")); dao.insert(session, report); + dao.insert(session, report); + session.commit(); db.assertDbUnit(getClass(), "insert-result.xml", "analysis_reports"); } + + @Test + public void update_all_to_status() { + when(system2.now()).thenReturn(DateUtils.parseDate("2014-09-26").getTime()); + + db.prepareDbUnit(getClass(), "update-all-to-status-pending.xml"); + + dao.cleanWithUpdateAllToPendingStatus(session); + session.commit(); + + db.assertDbUnit(getClass(), "update-all-to-status-pending-result.xml", "analysis_reports"); + } + + @Test + public void truncate() { + db.prepareDbUnit(getClass(), "any-analysis-reports.xml"); + + dao.cleanWithTruncate(session); + session.commit(); + + db.assertDbUnit(getClass(), "truncate-result.xml", "analysis_reports"); + } + + @Test + public void select_one_report_by_project_key() { + db.prepareDbUnit(getClass(), "select.xml"); + + final String projectKey = "123456789-987654321"; + List reports = dao.findByProjectKey(session, projectKey); + AnalysisReportDto report = reports.get(0); + + assertThat(reports).hasSize(1); + assertThat(report.getProjectKey()).isEqualTo(projectKey); + assertThat(report.getId()).isEqualTo(1); + } + + @Test + public void select_several_reports_by_project_key() { + db.prepareDbUnit(getClass(), "select.xml"); + + final String projectKey = "987654321-123456789"; + List reports = dao.findByProjectKey(session, projectKey); + + assertThat(reports).hasSize(2); + } } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml new file mode 100644 index 00000000000..66cdd2a55dc --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml @@ -0,0 +1,26 @@ + + + + + \ No newline at end of file diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml index 1275fb9bd3d..2dcc8a250b7 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml @@ -7,4 +7,12 @@ created_at="2014-09-24" updated_at="2014-09-26" /> + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml new file mode 100644 index 00000000000..6a347bb7795 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml @@ -0,0 +1,26 @@ + + + + + \ No newline at end of file diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/truncate-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/truncate-result.xml new file mode 100644 index 00000000000..e573e0c5b06 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/truncate-result.xml @@ -0,0 +1,3 @@ + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml new file mode 100644 index 00000000000..fd1f1c1d3e9 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml @@ -0,0 +1,46 @@ + + + + + + + \ No newline at end of file diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml new file mode 100644 index 00000000000..66cdd2a55dc --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml @@ -0,0 +1,26 @@ + + + + + \ No newline at end of file diff --git a/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java b/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java index 043fd5303e9..82ed36befae 100644 --- a/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java +++ b/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java @@ -34,7 +34,7 @@ public class AnalysisReportDto extends Dto { private String data; public enum Status { - PENDING + PENDING, WORKING } public String getProjectKey() { diff --git a/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportMapper.java b/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportMapper.java index 0d6af52b8bc..c32f0610070 100644 --- a/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportMapper.java @@ -19,9 +19,25 @@ */ package org.sonar.core.computation.db; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; + /** * since 5.0 */ public interface AnalysisReportMapper { void insert(AnalysisReportDto report); + + java.util.List selectByProjectKey(String projectKey); + + /** + * startup task use only + */ + void cleanWithUpdateAllToPendingStatus(@Param("status") AnalysisReportDto.Status status, @Param("updatedAt") Date updatedAt); + + /** + * startup task use only + */ + void cleanWithTruncate(); } diff --git a/sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml b/sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml index d7b54447271..785e71a775e 100644 --- a/sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml @@ -2,11 +2,34 @@ + + id, + project_key as projectKey, + report_status as status, + report_data as data, + created_at as createdAt, + updated_at as updatedAt + insert into analysis_reports (project_key, report_status, report_data, created_at, updated_at) values (#{projectKey}, #{status}, #{data}, #{createdAt}, #{updatedAt}) - + + update analysis_reports + set report_status=#{status}, updated_at=#{updatedAt} + + + + truncate table analysis_reports + + + + \ No newline at end of file -- 2.39.5