Skip to content

Commit

Permalink
cancel analysis when the snapshot is not found - SONAR-6340
Browse files Browse the repository at this point in the history
  • Loading branch information
teryk committed Mar 27, 2015
1 parent b8962af commit 7ebe878
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 79 deletions.
Expand Up @@ -32,6 +32,7 @@
import org.sonar.api.utils.log.Profiler; import org.sonar.api.utils.log.Profiler;
import org.sonar.batch.protocol.output.BatchReportReader; import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.core.component.ComponentDto; import org.sonar.core.component.ComponentDto;
import org.sonar.core.component.SnapshotDto;
import org.sonar.core.computation.db.AnalysisReportDto; import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis; import org.sonar.core.persistence.MyBatis;
Expand All @@ -41,11 +42,13 @@
import org.sonar.server.computation.step.ComputationSteps; import org.sonar.server.computation.step.ComputationSteps;
import org.sonar.server.db.DbClient; import org.sonar.server.db.DbClient;


import javax.annotation.Nullable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;


import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe; import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe;
import static org.sonar.api.utils.DateUtils.longToDate; import static org.sonar.api.utils.DateUtils.longToDate;
import static org.sonar.core.computation.db.AnalysisReportDto.Status.*;


public class ComputationService implements ServerComponent { public class ComputationService implements ServerComponent {


Expand All @@ -70,10 +73,15 @@ public void process(ReportQueue.Item item) {
Profiler profiler = Profiler.create(LOG).startDebug(String.format( Profiler profiler = Profiler.create(LOG).startDebug(String.format(
"Analysis of project %s (report %d)", item.dto.getProjectKey(), item.dto.getId())); "Analysis of project %s (report %d)", item.dto.getProjectKey(), item.dto.getId()));


ComponentDto project = loadProject(item); ComponentDto project = null;

try { try {
project = loadProject(item);
File reportDir = extractReportInDir(item); File reportDir = extractReportInDir(item);
BatchReportReader reader = new BatchReportReader(reportDir); BatchReportReader reader = new BatchReportReader(reportDir);
if (isSnapshotMissing(item, reader.readMetadata().getSnapshotId())) {
return;
}
ComputationContext context = new ComputationContext(reader, project); ComputationContext context = new ComputationContext(reader, project);
for (ComputationStep step : steps.orderedSteps()) { for (ComputationStep step : steps.orderedSteps()) {
if (ArrayUtils.contains(step.supportedProjectQualifiers(), context.getProject().qualifier())) { if (ArrayUtils.contains(step.supportedProjectQualifiers(), context.getProject().qualifier())) {
Expand All @@ -82,10 +90,9 @@ public void process(ReportQueue.Item item) {
stepProfiler.stopDebug(); stepProfiler.stopDebug();
} }
} }
item.dto.succeed(); item.dto.setStatus(SUCCESS);

} catch (Throwable e) { } catch (Throwable e) {
item.dto.fail(); item.dto.setStatus(FAILED);
throw Throwables.propagate(e); throw Throwables.propagate(e);
} finally { } finally {
item.dto.setFinishedAt(system.now()); item.dto.setFinishedAt(system.now());
Expand All @@ -110,28 +117,47 @@ private File extractReportInDir(ReportQueue.Item item) {
} }
} }


private ComponentDto loadProject(ReportQueue.Item queueItem) { private ComponentDto loadProject(ReportQueue.Item item) {
DbSession session = dbClient.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
return dbClient.componentDao().getByKey(session, queueItem.dto.getProjectKey()); return dbClient.componentDao().getByKey(session, item.dto.getProjectKey());
} finally { } finally {
MyBatis.closeQuietly(session); MyBatis.closeQuietly(session);
} }
} }


private void saveActivity(AnalysisReportDto report, ComponentDto project) { private boolean isSnapshotMissing(ReportQueue.Item item, long snapshotId) {
DbSession session = dbClient.openSession(false);
try {
SnapshotDto snapshot = dbClient.snapshotDao().getNullableByKey(session, snapshotId);
if (snapshot == null) {
item.dto.setStatus(CANCELLED);
LOG.info("Processing of report #{} is canceled because it was submitted while another report of the same project was already being processed.", item.dto.getId());
LOG.debug("The snapshot ID #{} provided by the report #{} does not exist anymore.", snapshotId, item.dto.getId());
}
return snapshot==null;
} finally {
MyBatis.closeQuietly(session);
}

}

private void saveActivity(AnalysisReportDto report, @Nullable ComponentDto project) {
Activity activity = new Activity(); Activity activity = new Activity();
activity.setType(Activity.Type.ANALYSIS_REPORT); activity.setType(Activity.Type.ANALYSIS_REPORT);
activity.setAction("LOG_ANALYSIS_REPORT"); activity.setAction("LOG_ANALYSIS_REPORT");
activity activity
.setData("key", String.valueOf(report.getId())) .setData("key", String.valueOf(report.getId()))
.setData("projectKey", project.key()) .setData("projectKey", report.getProjectKey())
.setData("projectName", project.name())
.setData("projectUuid", project.uuid())
.setData("status", String.valueOf(report.getStatus())) .setData("status", String.valueOf(report.getStatus()))
.setData("submittedAt", formatDateTimeNullSafe(longToDate(report.getCreatedAt()))) .setData("submittedAt", formatDateTimeNullSafe(longToDate(report.getCreatedAt())))
.setData("startedAt", formatDateTimeNullSafe(longToDate(report.getStartedAt()))) .setData("startedAt", formatDateTimeNullSafe(longToDate(report.getStartedAt())))
.setData("finishedAt", formatDateTimeNullSafe(longToDate(report.getFinishedAt()))); .setData("finishedAt", formatDateTimeNullSafe(longToDate(report.getFinishedAt())));
if (project != null) {
activity
.setData("projectName", project.name())
.setData("projectUuid", project.uuid());
}
activityService.save(activity); activityService.save(activity);
} }
} }
Expand Up @@ -29,6 +29,7 @@
import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis; import org.sonar.core.persistence.MyBatis;
import org.sonar.process.ProcessConstants; import org.sonar.process.ProcessConstants;
import org.sonar.server.computation.db.AnalysisReportDao;
import org.sonar.server.db.DbClient; import org.sonar.server.db.DbClient;


import javax.annotation.CheckForNull; import javax.annotation.CheckForNull;
Expand All @@ -41,17 +42,6 @@
import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING; import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING;


public class ReportQueue implements ServerComponent { public class ReportQueue implements ServerComponent {

public static class Item {
public final AnalysisReportDto dto;
public final File zipFile;

public Item(AnalysisReportDto dto, File zipFile) {
this.dto = dto;
this.zipFile = zipFile;
}
}

private final DbClient dbClient; private final DbClient dbClient;
private final Settings settings; private final Settings settings;


Expand All @@ -68,18 +58,10 @@ public Item add(String projectKey, InputStream reportData) {
try { try {
checkThatProjectExistsInDatabase(projectKey, session); checkThatProjectExistsInDatabase(projectKey, session);


// save report data on file. Directory is created if it does not exist yet. saveReportOnDisk(reportData, file);
FileUtils.copyInputStreamToFile(reportData, file); AnalysisReportDto dto = saveReportMetadataInDatabase(projectKey, uuid, session);


// add report metadata to the queue
AnalysisReportDto dto = new AnalysisReportDto()
.setProjectKey(projectKey)
.setStatus(PENDING)
.setUuid(uuid);
dbClient.analysisReportDao().insert(session, dto);
session.commit();
return new Item(dto, file); return new Item(dto, file);

} catch (Exception e) { } catch (Exception e) {
FileUtils.deleteQuietly(file); FileUtils.deleteQuietly(file);
throw new IllegalStateException("Fail to store analysis report of project " + projectKey, e); throw new IllegalStateException("Fail to store analysis report of project " + projectKey, e);
Expand All @@ -88,6 +70,24 @@ public Item add(String projectKey, InputStream reportData) {
} }
} }


private AnalysisReportDto saveReportMetadataInDatabase(String projectKey, String uuid, DbSession session) {
AnalysisReportDto dto = new AnalysisReportDto()
.setProjectKey(projectKey)
.setStatus(PENDING)
.setUuid(uuid);
dao().insert(session, dto);
session.commit();
return dto;
}

private AnalysisReportDao dao() {
return dbClient.analysisReportDao();
}

private void saveReportOnDisk(InputStream reportData, File file) throws IOException {
FileUtils.copyInputStreamToFile(reportData, file);
}

private void checkThatProjectExistsInDatabase(String projectKey, DbSession session) { private void checkThatProjectExistsInDatabase(String projectKey, DbSession session) {
dbClient.componentDao().getByKey(session, projectKey); dbClient.componentDao().getByKey(session, projectKey);
} }
Expand All @@ -96,7 +96,7 @@ public void remove(Item item) {
DbSession session = dbClient.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
FileUtils.deleteQuietly(item.zipFile); FileUtils.deleteQuietly(item.zipFile);
dbClient.analysisReportDao().delete(session, item.dto.getId()); dao().delete(session, item.dto.getId());
session.commit(); session.commit();
} finally { } finally {
MyBatis.closeQuietly(session); MyBatis.closeQuietly(session);
Expand All @@ -107,14 +107,14 @@ public void remove(Item item) {
public Item pop() { public Item pop() {
DbSession session = dbClient.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
AnalysisReportDto dto = dbClient.analysisReportDao().pop(session); AnalysisReportDto dto = dao().pop(session);
if (dto != null) { if (dto != null) {
File file = reportFileForUuid(dto.getUuid()); File file = reportFileForUuid(dto.getUuid());
if (file.exists()) { if (file.exists()) {
return new Item(dto, file); return new Item(dto, file);
} }
Loggers.get(getClass()).error("Analysis report not found: " + file.getAbsolutePath()); Loggers.get(getClass()).error("Analysis report not found: " + file.getAbsolutePath());
dbClient.analysisReportDao().delete(session, dto.getId()); dao().delete(session, dto.getId());
session.commit(); session.commit();
} }
return null; return null;
Expand All @@ -123,10 +123,10 @@ public Item pop() {
} }
} }


public List<AnalysisReportDto> findByProjectKey(String projectKey) { public List<AnalysisReportDto> selectByProjectKey(String projectKey) {
DbSession session = dbClient.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
return dbClient.analysisReportDao().selectByProjectKey(session, projectKey); return dao().selectByProjectKey(session, projectKey);
} finally { } finally {
MyBatis.closeQuietly(session); MyBatis.closeQuietly(session);
} }
Expand All @@ -145,7 +145,7 @@ public void clear() {


DbSession session = dbClient.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
dbClient.analysisReportDao().truncate(session); dao().truncate(session);
session.commit(); session.commit();
} finally { } finally {
MyBatis.closeQuietly(session); MyBatis.closeQuietly(session);
Expand All @@ -155,7 +155,7 @@ public void clear() {
public void resetToPendingStatus() { public void resetToPendingStatus() {
DbSession session = dbClient.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
dbClient.analysisReportDao().resetAllToPendingStatus(session); dao().resetAllToPendingStatus(session);
session.commit(); session.commit();
} finally { } finally {
MyBatis.closeQuietly(session); MyBatis.closeQuietly(session);
Expand All @@ -168,7 +168,7 @@ public void resetToPendingStatus() {
public List<AnalysisReportDto> all() { public List<AnalysisReportDto> all() {
DbSession session = dbClient.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
return dbClient.analysisReportDao().selectAll(session); return dao().selectAll(session);
} finally { } finally {
MyBatis.closeQuietly(session); MyBatis.closeQuietly(session);
} }
Expand All @@ -185,4 +185,14 @@ private File reportsDir() {
private File reportFileForUuid(String uuid) { private File reportFileForUuid(String uuid) {
return new File(reportsDir(), String.format("%s.zip", uuid)); return new File(reportsDir(), String.format("%s.zip", uuid));
} }

public static class Item {
public final AnalysisReportDto dto;
public final File zipFile;

public Item(AnalysisReportDto dto, File zipFile) {
this.dto = dto;
this.zipFile = zipFile;
}
}
} }

0 comments on commit 7ebe878

Please sign in to comment.