You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CeQueueDao.java 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.db.ce;
  21. import com.google.common.collect.ImmutableMap;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.Optional;
  25. import java.util.Set;
  26. import javax.annotation.Nullable;
  27. import org.apache.ibatis.session.RowBounds;
  28. import org.sonar.api.utils.System2;
  29. import org.sonar.db.Dao;
  30. import org.sonar.db.DbSession;
  31. import org.sonar.db.Pagination;
  32. import static java.util.Collections.emptyList;
  33. import static java.util.Collections.emptyMap;
  34. import static org.sonar.db.DatabaseUtils.executeLargeUpdates;
  35. import static org.sonar.db.ce.CeQueueDto.Status.IN_PROGRESS;
  36. import static org.sonar.db.ce.CeQueueDto.Status.PENDING;
  37. public class CeQueueDao implements Dao {
  38. private static final Pagination ONE_RESULT_PAGINATION = Pagination.forPage(1).andSize(1);
  39. private final System2 system2;
  40. public CeQueueDao(System2 system2) {
  41. this.system2 = system2;
  42. }
  43. /**
  44. * Ordered by ascending id: oldest to newest
  45. */
  46. public List<CeQueueDto> selectAllInAscOrder(DbSession session) {
  47. return mapper(session).selectAllInAscOrder();
  48. }
  49. public List<CeQueueDto> selectByQueryInDescOrder(DbSession dbSession, CeTaskQuery query, int pageSize) {
  50. if (query.isShortCircuitedByMainComponentUuids()
  51. || query.isOnlyCurrents()
  52. || query.getMaxExecutedAt() != null) {
  53. return emptyList();
  54. }
  55. return mapper(dbSession).selectByQueryInDescOrder(query, new RowBounds(0, pageSize));
  56. }
  57. public int countByQuery(DbSession dbSession, CeTaskQuery query) {
  58. if (query.isShortCircuitedByMainComponentUuids()
  59. || query.isOnlyCurrents()
  60. || query.getMaxExecutedAt() != null) {
  61. return 0;
  62. }
  63. return mapper(dbSession).countByQuery(query);
  64. }
  65. /**
  66. * Ordered by ascending id: oldest to newest
  67. */
  68. public List<CeQueueDto> selectByMainComponentUuid(DbSession session, String projectUuid) {
  69. return mapper(session).selectByMainComponentUuid(projectUuid);
  70. }
  71. public Optional<CeQueueDto> selectByUuid(DbSession session, String uuid) {
  72. return Optional.ofNullable(mapper(session).selectByUuid(uuid));
  73. }
  74. public List<CeQueueDto> selectPending(DbSession dbSession) {
  75. return mapper(dbSession).selectPending();
  76. }
  77. public List<CeQueueDto> selectWornout(DbSession dbSession) {
  78. return mapper(dbSession).selectWornout();
  79. }
  80. public List<CeQueueDto> selectInProgressStartedBefore(DbSession dbSession, long date) {
  81. return mapper(dbSession).selectInProgressStartedBefore(date);
  82. }
  83. public void resetTasksWithUnknownWorkerUUIDs(DbSession dbSession, Set<String> knownWorkerUUIDs) {
  84. if (knownWorkerUUIDs.isEmpty()) {
  85. mapper(dbSession).resetAllInProgressTasks(system2.now());
  86. } else {
  87. // executeLargeUpdates won't call the SQL command if knownWorkerUUIDs is empty
  88. executeLargeUpdates(knownWorkerUUIDs,
  89. uuids -> mapper(dbSession).resetTasksWithUnknownWorkerUUIDs(uuids, system2.now()));
  90. }
  91. }
  92. public CeQueueDto insert(DbSession session, CeQueueDto dto) {
  93. if (dto.getCreatedAt() == 0L || dto.getUpdatedAt() == 0L) {
  94. long now = system2.now();
  95. dto.setCreatedAt(now);
  96. dto.setUpdatedAt(now);
  97. }
  98. mapper(session).insert(dto);
  99. return dto;
  100. }
  101. public int deleteByUuid(DbSession session, String uuid) {
  102. return deleteByUuid(session, uuid, null);
  103. }
  104. public int deleteByUuid(DbSession session, String uuid, @Nullable DeleteIf deleteIf) {
  105. return mapper(session).deleteByUuid(uuid, deleteIf);
  106. }
  107. /**
  108. * Update all tasks for the specified worker uuid which are not PENDING to:
  109. * STATUS='PENDING', STARTED_AT=NULL, UPDATED_AT={now}.
  110. */
  111. public int resetToPendingForWorker(DbSession session, String workerUuid) {
  112. return mapper(session).resetToPendingForWorker(workerUuid, system2.now());
  113. }
  114. public int countByStatus(DbSession dbSession, CeQueueDto.Status status) {
  115. return mapper(dbSession).countByStatusAndMainComponentUuid(status, null);
  116. }
  117. public int countByStatusAndMainComponentUuid(DbSession dbSession, CeQueueDto.Status status, @Nullable String mainComponentUuid) {
  118. return mapper(dbSession).countByStatusAndMainComponentUuid(status, mainComponentUuid);
  119. }
  120. public Optional<Long> selectCreationDateOfOldestPendingByMainComponentUuid(DbSession dbSession, @Nullable String mainComponentUuid) {
  121. return Optional.ofNullable(mapper(dbSession).selectCreationDateOfOldestPendingByMainComponentUuid(mainComponentUuid));
  122. }
  123. /**
  124. * Counts entries in the queue with the specified status for each specified main component uuid.
  125. * The returned map doesn't contain any entry for main component uuids for which there is no entry in the queue (ie.
  126. * all entries have a value >= 0).
  127. */
  128. public Map<String, Integer> countByStatusAndMainComponentUuids(DbSession dbSession, CeQueueDto.Status status, Set<String> projectUuids) {
  129. if (projectUuids.isEmpty()) {
  130. return emptyMap();
  131. }
  132. ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
  133. executeLargeUpdates(
  134. projectUuids,
  135. partitionOfProjectUuids -> {
  136. List<QueueCount> i = mapper(dbSession).countByStatusAndMainComponentUuids(status, partitionOfProjectUuids);
  137. i.forEach(o -> builder.put(o.getMainComponentUuid(), o.getTotal()));
  138. });
  139. return builder.build();
  140. }
  141. public Optional<CeQueueDto> peek(DbSession session, String workerUuid) {
  142. List<String> eligibles = mapper(session).selectEligibleForPeek(ONE_RESULT_PAGINATION);
  143. if (eligibles.isEmpty()) {
  144. return Optional.empty();
  145. }
  146. String eligible = eligibles.get(0);
  147. return tryToPeek(session, eligible, workerUuid);
  148. }
  149. private Optional<CeQueueDto> tryToPeek(DbSession session, String eligibleTaskUuid, String workerUuid) {
  150. long now = system2.now();
  151. int touchedRows = mapper(session).updateIf(eligibleTaskUuid,
  152. new UpdateIf.NewProperties(IN_PROGRESS, workerUuid, now, now),
  153. new UpdateIf.OldProperties(PENDING));
  154. if (touchedRows != 1) {
  155. return Optional.empty();
  156. }
  157. CeQueueDto result = mapper(session).selectByUuid(eligibleTaskUuid);
  158. session.commit();
  159. return Optional.ofNullable(result);
  160. }
  161. private static CeQueueMapper mapper(DbSession session) {
  162. return session.getMapper(CeQueueMapper.class);
  163. }
  164. }