Browse Source

SONAR-12251 detect aborted attempt during processing of 1st project

tags/8.0
Sébastien Lesaint 5 years ago
parent
commit
020d9116cf

+ 1
- 1
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/charset/ColumnDef.java View File

@@ -90,7 +90,7 @@ public class ColumnDef {
@Override
public ColumnDef convert(ResultSet rs) throws SQLException {
String nullableText = rs.getString(7);
boolean nullable = "YES".equalsIgnoreCase(nullableText);
boolean nullable = "FIRST".equalsIgnoreCase(nullableText);

return new ColumnDef(
rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5), rs.getLong(6), nullable);

+ 23
- 11
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasures.java View File

@@ -54,9 +54,9 @@ public class PopulateLiveMeasures extends DataChange {

@Override
protected void execute(Context context) throws SQLException {
boolean firstAttempt = isFirstAttempt(context);
if (!firstAttempt) {
LOG.info("Retry detected (non empty table live_measures_p). Handle it");
ATTEMPT attempt = isFirstAttempt(context);
if (attempt != ATTEMPT.FIRST) {
LOG.info("Retry detected (non empty table live_measures_p or live_measures). Handling it");
}

long now = system2.now();
@@ -67,32 +67,44 @@ public class PopulateLiveMeasures extends DataChange {
" from snapshots s" +
" where" +
" s.islast = ?" +
(firstAttempt ? "" : " and not exists (select 1 from live_measures_p lmp where lmp.project_uuid=s.component_uuid)");
(attempt == ATTEMPT.ONE_PROJECT_OR_MORE ? " and not exists (select 1 from live_measures_p lmp where lmp.project_uuid=s.component_uuid)" : "");
try (Connection connection = createReadUncommittedConnection();
Select select = SelectImpl.create(db, connection, statement).setBoolean(1, true)) {
List<Row> rows = new ArrayList<>(projectBatchSize);
select.scroll(t -> {
rows.add(new Row(t.getString(1), t.getString(2)));
if (rows.size() == projectBatchSize) {
processProjectBatch(context, rows, firstAttempt, now);
processProjectBatch(context, rows, attempt, now);

rows.clear();
}
});

if (!rows.isEmpty()) {
processProjectBatch(context, rows, firstAttempt, now);
processProjectBatch(context, rows, attempt, now);
}
}
}

private static boolean isFirstAttempt(Context context) throws SQLException {
try (Select select = context.prepareSelect("select count(1) from live_measures_p")) {
return select.get(t -> t.getLong(1)) == 0;
private static ATTEMPT isFirstAttempt(Context context) throws SQLException {
try (
Select selectFromTempTable = context.prepareSelect("select count(1) from live_measures_p");
Select selectFromLiveMeasures = context.prepareSelect("select count(1) from live_measures")
) {
boolean projectsProcessed = selectFromTempTable.get(t -> t.getLong(1)) > 0;
if (projectsProcessed) {
return ATTEMPT.ONE_PROJECT_OR_MORE;
}
// we will count at most the data of one project => table should have little content => bad performance risk is low
return selectFromLiveMeasures.get(t -> t.getLong(1)) == 0 ? ATTEMPT.FIRST : ATTEMPT.PARTIAL;
}
}

private static void processProjectBatch(Context context, List<Row> rows, boolean firstAttempt, long now) throws SQLException {
private enum ATTEMPT {
FIRST, PARTIAL, ONE_PROJECT_OR_MORE
}

private static void processProjectBatch(Context context, List<Row> rows, ATTEMPT attempt, long now) throws SQLException {
MassUpdate massUpdate = context.prepareMassUpdate();
massUpdate.rowPluralName("live measures");
setSelect(rows, massUpdate);
@@ -104,7 +116,7 @@ public class PopulateLiveMeasures extends DataChange {
massUpdate.update("insert into live_measures_p (project_uuid) values (?)")
// we want to commit each project finished asap to avoid restarting them over in case of interruption
.setBatchSize(1);
LiveMeasurePopulationMultiHandler handler = new LiveMeasurePopulationMultiHandler(firstAttempt, rows, now);
LiveMeasurePopulationMultiHandler handler = new LiveMeasurePopulationMultiHandler(attempt == ATTEMPT.FIRST, rows, now);
massUpdate.execute(handler);

Set<String> notCommittedProjectUuids = handler.notCommittedProjectUuids;

+ 9
- 1
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest.java View File

@@ -87,7 +87,7 @@ public class PopulateLiveMeasuresTest {
}

@Test
public void do_not_fail_if_live_measure_of_component_already_partially_inserted() throws SQLException {
public void migration_is_reentrant_on_partially_processed_1st_project() throws SQLException {
generateProjectMeasures();

db.executeInsert(
@@ -102,6 +102,14 @@ public class PopulateLiveMeasuresTest {

underTest.execute();

assertThat(getLiveMeasures()).extracting(
field("COMPONENT_UUID"),
field("PROJECT_UUID"),
field("METRIC_ID"),
field("VALUE"),
field("TEXT_VALUE"),
field("VARIATION"),
field("MEASURE_DATA")).containsExactlyInAnyOrder(generateLiveMeasures());
}

private Function<Map<String, Object>, Object> field(String name) {

Loading…
Cancel
Save