<include refid="columns"/>
from project_branches pb
where need_issue_sync = ${_true}
- order by pb.updated_at, uuid
+ order by pb.updated_at desc, uuid
</select>
<update id="updateAllNeedIssueSync">
*/
package org.sonar.server.issue.index;
+import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.function.Function;
import java.util.stream.Collectors;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.log.Logger;
import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.SnapshotDto;
import static java.util.Collections.emptyMap;
import static org.sonar.db.ce.CeTaskTypes.BRANCH_ISSUE_SYNC;
String branchListForDisplay = branchInNeedOfIssueSync.stream().map(BranchDto::toString).collect(Collectors.joining(", "));
LOG.info("{} branch found in need of issue sync : {}", branchInNeedOfIssueSync.size(), branchListForDisplay);
- List<CeTaskSubmit> tasks = branchInNeedOfIssueSync.stream()
- .map(this::buildTaskSubmit)
- .collect(Collectors.toList());
- ceQueue.massSubmit(tasks);
+ List<String> projectUuids = new ArrayList<>(branchInNeedOfIssueSync.stream().map(BranchDto::getProjectUuid).collect(Collectors.toSet()));
+ LOG.info("{} projects found in need of issue sync.", projectUuids.size());
- dbSession.commit();
+ sortProjectUuids(dbSession, projectUuids);
+ Map<String, List<BranchDto>> branchesByProject = branchInNeedOfIssueSync.stream()
+ .collect(Collectors.groupingBy(BranchDto::getProjectUuid));
+
+ List<CeTaskSubmit> tasks = new ArrayList<>();
+ for (String projectUuid : projectUuids) {
+ List<BranchDto> branches = branchesByProject.get(projectUuid);
+ for (BranchDto branch : branches) {
+ tasks.add(buildTaskSubmit(branch));
+ }
+ }
+
+ ceQueue.massSubmit(tasks);
+ dbSession.commit();
}
}
+ private void sortProjectUuids(DbSession dbSession, List<String> projectUuids) {
+ Map<String, SnapshotDto> snapshotByProjectUuid = dbClient.snapshotDao()
+ .selectLastAnalysesByRootComponentUuids(dbSession, projectUuids).stream()
+ .collect(Collectors.toMap(SnapshotDto::getComponentUuid, Function.identity()));
+
+ projectUuids.sort(compareBySnapshot(snapshotByProjectUuid));
+ }
+
+ private static Comparator<String> compareBySnapshot(Map<String, SnapshotDto> snapshotByProjectUuid) {
+ return (uuid1, uuid2) -> {
+ SnapshotDto snapshot1 = snapshotByProjectUuid.get(uuid1);
+ SnapshotDto snapshot2 = snapshotByProjectUuid.get(uuid2);
+ if (snapshot1 == null) {
+ return 1;
+ }
+ if (snapshot2 == null) {
+ return -1;
+ }
+ return snapshot2.getCreatedAt().compareTo(snapshot1.getCreatedAt());
+ };
+ }
+
private void removeExistingIndexationTasks(DbSession dbSession) {
List<String> uuids = dbClient.ceQueueDao().selectAllInAscOrder(dbSession).stream()
.filter(p -> p.getTaskType().equals(BRANCH_ISSUE_SYNC))
*/
package org.sonar.server.issue.index;
+import java.util.Collection;
+import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.db.ce.CeActivityDto.Status;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.SnapshotDto;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.sonar.db.ce.CeTaskTypes.BRANCH_ISSUE_SYNC;
import static org.sonar.db.ce.CeTaskTypes.REPORT;
import static org.sonar.db.component.BranchType.BRANCH;
+import static org.sonar.db.component.SnapshotDto.STATUS_PROCESSED;
public class AsyncIssueIndexingImplTest {
"Indexation task deletion complete.");
}
+ @Test
+ public void order_by_last_analysis_date() {
+ BranchDto dto = new BranchDto()
+ .setBranchType(BRANCH)
+ .setKey("branch_1")
+ .setUuid("branch_uuid1")
+ .setProjectUuid("project_uuid1");
+ dbClient.branchDao().insert(dbTester.getSession(), dto);
+ dbTester.commit();
+ insertSnapshot("analysis_1", "project_uuid1", 1);
+
+ BranchDto dto2 = new BranchDto()
+ .setBranchType(BRANCH)
+ .setKey("branch_2")
+ .setUuid("branch_uuid2")
+ .setProjectUuid("project_uuid2");
+ dbClient.branchDao().insert(dbTester.getSession(), dto2);
+ dbTester.commit();
+ insertSnapshot("analysis_2", "project_uuid2", 2);
+
+ underTest.triggerOnIndexCreation();
+
+ verify(ceQueue, times(2)).prepareSubmit();
+
+ ArgumentCaptor<Collection<CeTaskSubmit>> captor = ArgumentCaptor.forClass(Collection.class);
+
+ verify(ceQueue, times(1)).massSubmit(captor.capture());
+ List<Collection<CeTaskSubmit>> captures = captor.getAllValues();
+ assertThat(captures).hasSize(1);
+ Collection<CeTaskSubmit> tasks = captures.get(0);
+ assertThat(tasks).hasSize(2);
+ assertThat(tasks)
+ .extracting(p -> p.getComponent().get().getUuid())
+ .containsExactly("branch_uuid2", "branch_uuid1");
+
+ assertThat(logTester.logs(LoggerLevel.INFO))
+ .contains("2 projects found in need of issue sync.");
+ }
+
+ private SnapshotDto insertSnapshot(String analysisUuid, String projectUuid, long createdAt) {
+ SnapshotDto snapshot = new SnapshotDto()
+ .setUuid(analysisUuid)
+ .setComponentUuid(projectUuid)
+ .setStatus(STATUS_PROCESSED)
+ .setCreatedAt(createdAt)
+ .setLast(true);
+ dbTester.getDbClient().snapshotDao().insert(dbTester.getSession(), snapshot);
+ dbTester.commit();
+ return snapshot;
+ }
+
}