aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2016-10-12 17:30:41 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2016-10-12 18:11:08 +0200
commit2bf5b53cdb3c31bcac0b242393adeb72a01cdede (patch)
tree43902cca22c86be5cbd873bfc8815d77ff397dc6
parent5ce0d722397b1811ed3e7a150d65a62cf33af43a (diff)
downloadsonarqube-2bf5b53cdb3c31bcac0b242393adeb72a01cdede.tar.gz
sonarqube-2bf5b53cdb3c31bcac0b242393adeb72a01cdede.zip
SONAR-8222 Update project measures index at the end of each project analysis
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java2
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStep.java45
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresIndexer.java13
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresResultSetIterator.java13
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStepTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStepTest.java51
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresIndexerTest.java45
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresResultSetIteratorTest.java44
10 files changed, 205 insertions, 17 deletions
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
index be426f6f7b7..fadc3875c60 100644
--- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
@@ -112,6 +112,7 @@ import org.sonar.server.plugins.InstalledPluginReferentialFactory;
import org.sonar.server.plugins.ServerExtensionInstaller;
import org.sonar.server.plugins.privileged.PrivilegedPluginsBootstraper;
import org.sonar.server.plugins.privileged.PrivilegedPluginsStopper;
+import org.sonar.server.project.es.ProjectMeasuresIndexer;
import org.sonar.server.property.InternalPropertiesImpl;
import org.sonar.server.qualityprofile.QProfileLookup;
import org.sonar.server.qualityprofile.QProfileProjectOperations;
@@ -322,6 +323,7 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
NewAlerts.class,
NewAlerts.newMetadata(),
ComponentCleanerService.class,
+ ProjectMeasuresIndexer.class,
// views
ViewIndexer.class,
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
index e1a8a4763d3..0f7d829a708 100644
--- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
@@ -88,7 +88,7 @@ public class ComputeEngineContainerImplTest {
assertThat(picoContainer.getComponentAdapters())
.hasSize(
CONTAINER_ITSELF
- + 73 // level 4
+ + 74 // level 4
+ 4 // content of CeConfigurationModule
+ 3 // content of CeHttpModule
+ 5 // content of CeQueueModule
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStep.java
new file mode 100644
index 00000000000..3250a46d62d
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStep.java
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.task.projectanalysis.step;
+
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
+import org.sonar.server.computation.task.step.ComputationStep;
+import org.sonar.server.project.es.ProjectMeasuresIndexer;
+
+public class IndexProjectMeasuresStep implements ComputationStep {
+
+ private final ProjectMeasuresIndexer indexer;
+ private final TreeRootHolder treeRootHolder;
+
+ public IndexProjectMeasuresStep(ProjectMeasuresIndexer indexer, TreeRootHolder treeRootHolder) {
+ this.indexer = indexer;
+ this.treeRootHolder = treeRootHolder;
+ }
+
+ @Override
+ public void execute() {
+ indexer.index(treeRootHolder.getRoot().getUuid());
+ }
+
+ @Override
+ public String getDescription() {
+ return "Index project measures";
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java
index 30e36ec7588..55c66df8e5c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java
@@ -107,6 +107,7 @@ public class ReportComputationSteps extends AbstractComputationSteps {
// ES indexing is done after all db changes
IndexIssuesStep.class,
IndexTestsStep.class,
+ IndexProjectMeasuresStep.class,
// notifications are sent at the end, so that webapp displays up-to-date information
SendIssueNotificationsStep.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresIndexer.java
index 2322ba94a11..0b933b0950e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresIndexer.java
@@ -21,6 +21,7 @@
package org.sonar.server.project.es;
import java.util.Iterator;
+import javax.annotation.Nullable;
import org.elasticsearch.action.index.IndexRequest;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
@@ -43,16 +44,20 @@ public class ProjectMeasuresIndexer extends BaseIndexer {
@Override
protected long doIndex(long lastUpdatedAt) {
- doIndex(createBulkIndexer(false));
- return 0L;
+ return doIndex(createBulkIndexer(false), (String) null);
}
- private void doIndex(BulkIndexer bulk) {
+ public void index(String projectUuid) {
+ index(lastUpdatedAt -> doIndex(createBulkIndexer(false), projectUuid));
+ }
+
+ private long doIndex(BulkIndexer bulk, @Nullable String projectUuid) {
DbSession dbSession = dbClient.openSession(false);
try {
- ProjectMeasuresResultSetIterator rowIt = ProjectMeasuresResultSetIterator.create(dbClient, dbSession);
+ ProjectMeasuresResultSetIterator rowIt = ProjectMeasuresResultSetIterator.create(dbClient, dbSession, projectUuid);
doIndex(bulk, rowIt);
rowIt.close();
+ return 0L;
} finally {
dbClient.closeSession(dbSession);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresResultSetIterator.java b/server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresResultSetIterator.java
index a936c85789a..47ad6f59f75 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresResultSetIterator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/es/ProjectMeasuresResultSetIterator.java
@@ -24,6 +24,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
+import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes;
@@ -44,17 +45,25 @@ public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectM
"LEFT OUTER JOIN snapshots s ON s.component_uuid=p.uuid AND s.islast=? " +
"WHERE p.enabled=? AND p.scope=? AND p.qualifier=?";
+ private static final String PROJECT_FILTER = " AND p.uuid=?";
+
private ProjectMeasuresResultSetIterator(PreparedStatement stmt) throws SQLException {
super(stmt);
}
- static ProjectMeasuresResultSetIterator create(DbClient dbClient, DbSession session) {
+ static ProjectMeasuresResultSetIterator create(DbClient dbClient, DbSession session, @Nullable String projectUuid) {
try {
- PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, SQL_ALL);
+
+ String sql = SQL_ALL;
+ sql += projectUuid == null ? "" : PROJECT_FILTER;
+ PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, sql);
stmt.setBoolean(1, true);
stmt.setBoolean(2, true);
stmt.setString(3, Scopes.PROJECT);
stmt.setString(4, Qualifiers.PROJECT);
+ if (projectUuid != null) {
+ stmt.setString(5, projectUuid);
+ }
return new ProjectMeasuresResultSetIterator(stmt);
} catch (SQLException e) {
throw new IllegalStateException("Fail to prepare SQL request to select all project measures", e);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStepTest.java
index df1fc8c235f..663b7159a69 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStepTest.java
@@ -26,8 +26,8 @@ import org.sonar.server.issue.index.IssueIndexer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.*;
-import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.*;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
public class IndexIssuesStepTest {
@@ -38,7 +38,7 @@ public class IndexIssuesStepTest {
.setRoot(builder(PROJECT, 1).setUuid(PROJECT_UUID).setKey("PROJECT_KEY").build());
@Test
- public void call_indexers() {
+ public void call_indexer() {
IssueIndexer issueIndexer = mock(IssueIndexer.class);
IndexIssuesStep underTest = new IndexIssuesStep(issueIndexer, treeRootHolder);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStepTest.java
new file mode 100644
index 00000000000..bda9ddb020c
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStepTest.java
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.task.projectanalysis.step;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
+import org.sonar.server.project.es.ProjectMeasuresIndexer;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
+
+public class IndexProjectMeasuresStepTest {
+
+ static String PROJECT_UUID = "PROJECT_UUID";
+
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
+ .setRoot(builder(PROJECT, 1).setUuid(PROJECT_UUID).setKey("PROJECT_KEY").build());
+
+ @Test
+ public void call_indexer() {
+ ProjectMeasuresIndexer indexer = mock(ProjectMeasuresIndexer.class);
+ IndexProjectMeasuresStep underTest = new IndexProjectMeasuresStep(indexer, treeRootHolder);
+
+ underTest.execute();
+
+ verify(indexer).index(PROJECT_UUID);
+ }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresIndexerTest.java
index 8867fc6d9a5..6b562b439bc 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresIndexerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresIndexerTest.java
@@ -20,15 +20,22 @@
package org.sonar.server.project.es;
+import java.util.Date;
+import org.elasticsearch.action.search.SearchRequestBuilder;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.config.MapSettings;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
import org.sonar.server.es.EsTester;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
+import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.sonar.db.component.ComponentTesting.newProjectDto;
import static org.sonar.server.project.es.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES;
import static org.sonar.server.project.es.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURES;
@@ -53,7 +60,7 @@ public class ProjectMeasuresIndexerTest {
}
@Test
- public void index_one_project() {
+ public void index_all_project() {
componentDbTester.insertProjectAndSnapshot(newProjectDto());
underTest.index();
@@ -61,4 +68,40 @@ public class ProjectMeasuresIndexerTest {
assertThat(esTester.countDocuments(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES)).isEqualTo(1);
}
+ @Test
+ public void index_one_project() throws Exception {
+ ComponentDto project = newProjectDto();
+ componentDbTester.insertProjectAndSnapshot(project);
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+
+ underTest.index(project.uuid());
+
+ assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES)).containsOnly(project.uuid());
+ }
+
+ @Test
+ public void update_existing_document_when_indexing_one_project() throws Exception {
+ String uuid = "PROJECT-UUID";
+ esTester.putDocuments(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES, new ProjectMeasuresDoc()
+ .setId(uuid)
+ .setKey("Old Key")
+ .setName("Old Name")
+ .setAnalysedAt(new Date(1_000_000L)));
+ ComponentDto project = newProjectDto(uuid).setKey("New key").setName("New name");
+ SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
+
+ underTest.index(project.uuid());
+
+ assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES)).containsOnly(uuid);
+ SearchRequestBuilder request = esTester.client()
+ .prepareSearch(INDEX_PROJECT_MEASURES)
+ .setTypes(TYPE_PROJECT_MEASURES)
+ .setQuery(boolQuery().must(matchAllQuery()).filter(
+ boolQuery()
+ .must(termQuery("_id", uuid))
+ .must(termQuery(ProjectMeasuresIndexDefinition.FIELD_KEY, "New key"))
+ .must(termQuery(ProjectMeasuresIndexDefinition.FIELD_NAME, "New name"))
+ .must(termQuery(ProjectMeasuresIndexDefinition.FIELD_ANALYSED_AT, new Date(analysis.getCreatedAt())))));
+ assertThat(request.get().getHits()).hasSize(1);
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresResultSetIteratorTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresResultSetIteratorTest.java
index 48c889f00af..b018d1b72f0 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresResultSetIteratorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/project/es/ProjectMeasuresResultSetIteratorTest.java
@@ -23,6 +23,7 @@ package org.sonar.server.project.es;
import com.google.common.collect.Maps;
import java.util.Date;
import java.util.Map;
+import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
@@ -54,7 +55,7 @@ public class ProjectMeasuresResultSetIteratorTest {
ComponentDto project = newProjectDto().setKey("Project-Key").setName("Project Name");
SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
- Map<String, ProjectMeasuresDoc> docsById = docsById();
+ Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById();
assertThat(docsById).hasSize(1);
ProjectMeasuresDoc doc = docsById.get(project.uuid());
@@ -71,7 +72,7 @@ public class ProjectMeasuresResultSetIteratorTest {
componentDbTester.insertProjectAndSnapshot(newProjectDto());
componentDbTester.insertProjectAndSnapshot(newProjectDto());
- assertThat(docsById()).hasSize(3);
+ assertThat(createResultSetAndReturnDocsById()).hasSize(3);
}
@Test
@@ -80,7 +81,7 @@ public class ProjectMeasuresResultSetIteratorTest {
dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setLast(false));
dbSession.commit();
- Map<String, ProjectMeasuresDoc> docsById = docsById();
+ Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById();
assertThat(docsById).hasSize(1);
ProjectMeasuresDoc doc = docsById.get(project.uuid());
@@ -106,15 +107,46 @@ public class ProjectMeasuresResultSetIteratorTest {
assertResultSetIsEmpty();
}
- private Map<String, ProjectMeasuresDoc> docsById() {
- ProjectMeasuresResultSetIterator it = ProjectMeasuresResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession());
+ @Test
+ public void return_only_docs_from_given_project() throws Exception {
+ ComponentDto project = newProjectDto();
+ SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+
+ Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(project.uuid());
+
+ assertThat(docsById).hasSize(1);
+ ProjectMeasuresDoc doc = docsById.get(project.uuid());
+ assertThat(doc).isNotNull();
+ assertThat(doc.getId()).isEqualTo(project.uuid());
+ assertThat(doc.getKey()).isNotNull().isEqualTo(project.getKey());
+ assertThat(doc.getName()).isNotNull().isEqualTo(project.name());
+ assertThat(doc.getAnalysedAt()).isNotNull().isEqualTo(new Date(analysis.getCreatedAt()));
+ }
+
+ @Test
+ public void return_nothing_on_unknown_project() throws Exception {
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+
+ Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById("UNKNOWN");
+
+ assertThat(docsById).isEmpty();
+ }
+
+ private Map<String, ProjectMeasuresDoc> createResultSetAndReturnDocsById() {
+ return createResultSetAndReturnDocsById(null);
+ }
+
+ private Map<String, ProjectMeasuresDoc> createResultSetAndReturnDocsById(@Nullable String projectUuid) {
+ ProjectMeasuresResultSetIterator it = ProjectMeasuresResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), projectUuid);
Map<String, ProjectMeasuresDoc> docsById = Maps.uniqueIndex(it, ProjectMeasuresDoc::getId);
it.close();
return docsById;
}
private void assertResultSetIsEmpty() {
- assertThat(docsById()).isEmpty();
+ assertThat(createResultSetAndReturnDocsById()).isEmpty();
}
}