SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep,
IndexProjectIssuesStep indexProjectIssuesStep,
SwitchSnapshotStep switchSnapshotStep,
- DbCleanerStep dbCleanerStep) {
- steps = ImmutableList.of(getAndSetProjectStep, synchronizeProjectPermissionsStep, switchSnapshotStep, dbCleanerStep, indexProjectIssuesStep);
+ DataCleanerStep dataCleanerStep) {
+ steps = ImmutableList.of(getAndSetProjectStep, synchronizeProjectPermissionsStep, switchSnapshotStep, dataCleanerStep, indexProjectIssuesStep);
}
public List<ComputationStep> steps() {
--- /dev/null
+/*
+ * 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.sonar.api.config.Settings;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.purge.PurgeConfiguration;
+import org.sonar.server.issue.index.IssueIndex;
+
+import java.util.Date;
+
+public class DataCleanerStep implements ComputationStep {
+ private final DefaultPurgeTask purgeTask;
+ private final IssueIndex issueIndex;
+ private final Settings settings;
+
+ public DataCleanerStep(DefaultPurgeTask purgeTask, IssueIndex issueIndex, Settings settings) {
+ this.purgeTask = purgeTask;
+ this.issueIndex = issueIndex;
+ this.settings = settings;
+ }
+
+ @Override
+ public void execute(DbSession session, AnalysisReportDto report) {
+ Long projectId = report.getProject().getId();
+ purgeTask.purge(projectId);
+ issueIndex.deleteClosedIssuesOfProjectBefore(report.getProjectUuid(), deleteIssuesBeforeThisDate(projectId));
+ }
+
+ private Date deleteIssuesBeforeThisDate(Long resourceId) {
+ return PurgeConfiguration.newDefaultPurgeConfiguration(resourceId, settings).maxLiveDateOfClosedIssues();
+ }
+
+ @Override
+ public String description() {
+ return "Purge database";
+ }
+}
+++ /dev/null
-/*
- * 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.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
-import org.sonar.core.persistence.DbSession;
-
-public class DbCleanerStep implements ComputationStep {
- private final DefaultPurgeTask purgeTask;
-
- public DbCleanerStep(DefaultPurgeTask purgeTask) {
- this.purgeTask = purgeTask;
- }
-
- @Override
- public void execute(DbSession session, AnalysisReportDto report) {
- purgeTask.purge(report.getProject().getId());
- }
-
- @Override
- public String description() {
- return "Purge database";
- }
-}
getClient().prepareDeleteByQuery(getIndexName()).setQuery(queryBuilder).get();
}
- public void deleteByProjectUuidBefore(String uuid, Date beforeDate) {
- // TODO to implement
+ public void deleteClosedIssuesOfProjectBefore(String uuid, Date beforeDate) {
+ FilterBuilder projectFilter = FilterBuilders.boolFilter().must(FilterBuilders.termsFilter(IssueNormalizer.IssueField.PROJECT.field(), uuid));
+ FilterBuilder dateFilter = FilterBuilders.rangeFilter(IssueNormalizer.IssueField.ISSUE_CLOSE_DATE.field()).lt(beforeDate.getTime());
+ QueryBuilder queryBuilder = QueryBuilders.filteredQuery(
+ QueryBuilders.matchAllQuery(),
+ FilterBuilders.andFilter(projectFilter, dateFilter)
+ );
+
+ getClient().prepareDeleteByQuery(getIndexName()).setQuery(queryBuilder).get();
}
/* Build main filter (match based) */
pico.addSingleton(SynchronizeProjectPermissionsStep.class);
pico.addSingleton(IndexProjectIssuesStep.class);
pico.addSingleton(SwitchSnapshotStep.class);
- pico.addSingleton(DbCleanerStep.class);
+ pico.addSingleton(DataCleanerStep.class);
pico.add(AnalysisReportQueue.class);
pico.addSingleton(AnalysisReportTaskLauncher.class);
pico.addSingleton(AnalysisReportWebService.class);
private SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep;
private IndexProjectIssuesStep indexProjectIssuesStep;
private SwitchSnapshotStep switchSnapshotStep;
- private DbCleanerStep dbCleanerStep;
+ private DataCleanerStep dataCleanerStep;
@Before
public void before() {
synchronizeProjectPermissionsStep = mock(SynchronizeProjectPermissionsStep.class);
indexProjectIssuesStep = mock(IndexProjectIssuesStep.class);
switchSnapshotStep = mock(SwitchSnapshotStep.class);
- dbCleanerStep = mock(DbCleanerStep.class);
+ dataCleanerStep = mock(DataCleanerStep.class);
- sut = new ComputationStepRegistry(getAndSetProjectStep, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep, dbCleanerStep);
+ sut = new ComputationStepRegistry(getAndSetProjectStep, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep, dataCleanerStep);
}
@Test
public void steps_returned_in_the_right_order() throws Exception {
- assertThat(sut.steps()).containsExactly(getAndSetProjectStep, synchronizeProjectPermissionsStep, switchSnapshotStep, dbCleanerStep, indexProjectIssuesStep);
+ assertThat(sut.steps()).containsExactly(getAndSetProjectStep, synchronizeProjectPermissionsStep, switchSnapshotStep, dataCleanerStep, indexProjectIssuesStep);
}
}
--- /dev/null
+/*
+ * 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.config.Settings;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.issue.index.IssueIndex;
+
+import java.util.Date;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+public class DataCleanerStepTest {
+
+ private DataCleanerStep sut;
+ private DefaultPurgeTask purgeTask;
+ private IssueIndex issueIndex;
+ private Settings settings;
+
+ @Before
+ public void before() {
+ this.purgeTask = mock(DefaultPurgeTask.class);
+ this.issueIndex = mock(IssueIndex.class);
+ this.settings = mock(Settings.class);
+
+ this.sut = new DataCleanerStep(purgeTask, issueIndex, settings);
+ }
+
+ @Test
+ public void call_purge_method_of_the_purge_task() {
+ AnalysisReportDto report = mock(AnalysisReportDto.class);
+ when(report.getProject()).thenReturn(mock(ComponentDto.class));
+
+ sut.execute(mock(DbSession.class), report);
+
+ verify(purgeTask).purge(any(Long.class));
+ verify(issueIndex).deleteClosedIssuesOfProjectBefore(anyString(), any(Date.class));
+ }
+}
+++ /dev/null
-/*
- * 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.sonar.api.config.Settings;
-import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
-import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeProfiler;
-
-import static org.mockito.Mockito.mock;
-
-public class DbCleanStepTest {
-
- private DbCleanerStep sut;
-
- @Before
- public void before() {
- sut = new DbCleanerStep(new DefaultPurgeTask(mock(PurgeDao.class), mock(Settings.class), mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class)));
- }
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
-import org.sonar.core.persistence.DbSession;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.*;
-
-public class DbCleanerStepTest {
-
- private DbCleanerStep sut;
- private DefaultPurgeTask purgeTask;
-
- @Before
- public void before() {
- this.purgeTask = mock(DefaultPurgeTask.class);
- this.sut = new DbCleanerStep(purgeTask);
- }
-
- @Test
- public void call_purge_method_of_the_purge_task() {
- AnalysisReportDto report = mock(AnalysisReportDto.class);
- when(report.getProject()).thenReturn(mock(ComponentDto.class));
-
- sut.execute(mock(DbSession.class), report);
-
- verify(purgeTask).purge(any(Long.class));
- }
-
-}
assertThat(searchResult.getHits()).isEmpty();
assertThat(index.countAll()).isEqualTo(1);
}
+
+ @Test
+ public void delete_closed_issues_from_one_project_older_than_specific_date() {
+ // ARRANGE
+ Date today = new Date();
+ Date yesterday = org.apache.commons.lang.time.DateUtils.addDays(today, -1);
+ Date beforeYesterday = org.apache.commons.lang.time.DateUtils.addDays(yesterday, -1);
+
+ tester.get(IssueDao.class).insert(session, IssueTesting.newDto(rule, file, project).setIssueCloseDate(today));
+ tester.get(IssueDao.class).insert(session, IssueTesting.newDto(rule, file, project).setIssueCloseDate(beforeYesterday));
+ tester.get(IssueDao.class).insert(session, IssueTesting.newDto(rule, file, project));
+ session.commit();
+ assertThat(index.countAll()).isEqualTo(3L);
+
+ // ACT
+ index.deleteClosedIssuesOfProjectBefore(project.uuid(), yesterday);
+
+ // ASSERT
+ List<Issue> issues = index.search(IssueQuery.builder().componentRootUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits();
+ List<Date> dates = newArrayList();
+ for (Issue issue : issues) {
+ dates.add(issue.closeDate());
+ }
+
+ assertThat(index.countAll()).isEqualTo(2);
+ assertThat(dates).containsOnly(null, today);
+ }
}
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.TimeUtils;
import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
import org.sonar.core.purge.PurgeConfiguration;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.plugins.dbcleaner.api.PurgeTask;
+import static org.sonar.core.purge.PurgeConfiguration.newDefaultPurgeConfiguration;
+
/**
* @since 2.14
*/
public class DefaultPurgeTask implements PurgeTask {
private static final Logger LOG = LoggerFactory.getLogger(DefaultPurgeTask.class);
private final PurgeProfiler profiler;
- private PurgeDao purgeDao;
- private Settings settings;
- private DefaultPeriodCleaner periodCleaner;
+ private final PurgeDao purgeDao;
+ private final Settings settings;
+ private final DefaultPeriodCleaner periodCleaner;
public DefaultPurgeTask(PurgeDao purgeDao, Settings settings, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler) {
this.purgeDao = purgeDao;
private void doPurge(long resourceId) {
try {
- purgeDao.purge(newConf(resourceId));
+ purgeDao.purge(newPurgeConfigurationOnResource(resourceId));
} catch (Exception e) {
// purge errors must no fail the batch
LOG.error("Fail to purge data [id=" + resourceId + "]", e);
}
}
- private PurgeConfiguration newConf(long resourceId) {
- String[] scopes = new String[] {Scopes.FILE};
- if (settings.getBoolean(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)) {
- scopes = new String[] {Scopes.DIRECTORY, Scopes.FILE};
- }
- return new PurgeConfiguration(resourceId, scopes, settings.getInt(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES));
+ public PurgeConfiguration newPurgeConfigurationOnResource(long resourceId) {
+ return newDefaultPurgeConfiguration(resourceId, settings);
}
}
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang.time.DateUtils;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.System2;
+import org.sonar.core.computation.dbcleaner.DbCleanerConstants;
import javax.annotation.CheckForNull;
this.system2 = system2;
}
+ public static PurgeConfiguration newDefaultPurgeConfiguration(long resourceId, Settings settings) {
+ String[] scopes = new String[] {Scopes.FILE};
+ if (settings.getBoolean(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)) {
+ scopes = new String[] {Scopes.DIRECTORY, Scopes.FILE};
+ }
+ return new PurgeConfiguration(resourceId, scopes, settings.getInt(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES));
+ }
+
public long rootProjectId() {
return rootProjectId;
}