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.

CeQueueDaoTest.java 34KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 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.base.Function;
  22. import com.google.common.collect.ImmutableMap;
  23. import com.google.common.collect.ImmutableSet;
  24. import java.util.Collections;
  25. import java.util.HashMap;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.Optional;
  29. import java.util.Random;
  30. import java.util.function.Consumer;
  31. import java.util.stream.Collectors;
  32. import java.util.stream.Stream;
  33. import javax.annotation.Nullable;
  34. import org.junit.Rule;
  35. import org.junit.Test;
  36. import org.mockito.Mockito;
  37. import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
  38. import org.sonar.api.impl.utils.TestSystem2;
  39. import org.sonar.api.utils.System2;
  40. import org.sonar.db.DbTester;
  41. import org.sonar.db.component.ComponentDto;
  42. import static com.google.common.collect.Lists.newArrayList;
  43. import static java.util.Collections.singletonList;
  44. import static org.assertj.core.api.Assertions.assertThat;
  45. import static org.assertj.core.api.Assertions.entry;
  46. import static org.assertj.core.groups.Tuple.tuple;
  47. import static org.mockito.Mockito.mock;
  48. import static org.mockito.Mockito.when;
  49. import static org.sonar.db.ce.CeQueueDto.Status.IN_PROGRESS;
  50. import static org.sonar.db.ce.CeQueueDto.Status.PENDING;
  51. import static org.sonar.db.ce.CeQueueTesting.newCeQueueDto;
  52. import static org.sonar.db.ce.CeQueueTesting.reset;
  53. public class CeQueueDaoTest {
  54. private static final long INIT_TIME = 1_450_000_000_000L;
  55. private static final String TASK_UUID_1 = "TASK_1";
  56. private static final String TASK_UUID_2 = "TASK_2";
  57. private static final String MAIN_COMPONENT_UUID_1 = "PROJECT_1";
  58. private static final String MAIN_COMPONENT_UUID_2 = "PROJECT_2";
  59. private static final String TASK_UUID_3 = "TASK_3";
  60. private static final String SELECT_QUEUE_UUID_AND_STATUS_QUERY = "select uuid,status from ce_queue";
  61. private static final String SUBMITTER_LOGIN = "submitter uuid";
  62. private static final String WORKER_UUID_1 = "worker uuid 1";
  63. private static final String WORKER_UUID_2 = "worker uuid 2";
  64. private TestSystem2 system2 = new TestSystem2().setNow(INIT_TIME);
  65. @Rule
  66. public DbTester db = DbTester.create(system2);
  67. private System2 mockedSystem2 = mock(System2.class);
  68. private System2 alwaysIncreasingSystem2 = new AlwaysIncreasingSystem2();
  69. private CeQueueDao underTest = new CeQueueDao(system2);
  70. private CeQueueDao underTestWithSystem2Mock = new CeQueueDao(mockedSystem2);
  71. private CeQueueDao underTestAlwaysIncreasingSystem2 = new CeQueueDao(alwaysIncreasingSystem2);
  72. @Test
  73. public void insert_populates_createdAt_and_updateAt_from_System2_with_same_value_if_any_is_not_set() {
  74. long now = 1_334_333L;
  75. CeQueueDto dto = new CeQueueDto()
  76. .setTaskType(CeTaskTypes.REPORT)
  77. .setComponentUuid(MAIN_COMPONENT_UUID_1)
  78. .setStatus(PENDING)
  79. .setSubmitterUuid(SUBMITTER_LOGIN);
  80. mockSystem2ForSingleCall(now);
  81. underTestWithSystem2Mock.insert(db.getSession(), dto.setUuid(TASK_UUID_1));
  82. mockSystem2ForSingleCall(now);
  83. underTestWithSystem2Mock.insert(db.getSession(), dto.setUuid(TASK_UUID_2).setCreatedAt(8_000_999L).setUpdatedAt(0));
  84. mockSystem2ForSingleCall(now);
  85. underTestWithSystem2Mock.insert(db.getSession(), dto.setUuid(TASK_UUID_3).setCreatedAt(0).setUpdatedAt(8_000_999L));
  86. mockSystem2ForSingleCall(now);
  87. String uuid4 = "uuid 4";
  88. underTestWithSystem2Mock.insert(db.getSession(), dto.setUuid(uuid4).setCreatedAt(6_888_777L).setUpdatedAt(8_000_999L));
  89. db.getSession().commit();
  90. Stream.of(TASK_UUID_1, TASK_UUID_2, TASK_UUID_3)
  91. .forEach(uuid -> {
  92. CeQueueDto saved = underTest.selectByUuid(db.getSession(), uuid).get();
  93. assertThat(saved.getUuid()).isEqualTo(uuid);
  94. assertThat(saved.getTaskType()).isEqualTo(CeTaskTypes.REPORT);
  95. assertThat(saved.getComponentUuid()).isEqualTo(MAIN_COMPONENT_UUID_1);
  96. assertThat(saved.getStatus()).isEqualTo(PENDING);
  97. assertThat(saved.getSubmitterUuid()).isEqualTo(SUBMITTER_LOGIN);
  98. assertThat(saved.getWorkerUuid()).isNull();
  99. assertThat(saved.getCreatedAt()).isEqualTo(now);
  100. assertThat(saved.getUpdatedAt()).isEqualTo(now);
  101. assertThat(saved.getStartedAt()).isNull();
  102. });
  103. CeQueueDto saved = underTest.selectByUuid(db.getSession(), uuid4).get();
  104. assertThat(saved.getUuid()).isEqualTo(uuid4);
  105. assertThat(saved.getTaskType()).isEqualTo(CeTaskTypes.REPORT);
  106. assertThat(saved.getComponentUuid()).isEqualTo(MAIN_COMPONENT_UUID_1);
  107. assertThat(saved.getStatus()).isEqualTo(PENDING);
  108. assertThat(saved.getSubmitterUuid()).isEqualTo(SUBMITTER_LOGIN);
  109. assertThat(saved.getWorkerUuid()).isNull();
  110. assertThat(saved.getCreatedAt()).isEqualTo(6_888_777L);
  111. assertThat(saved.getUpdatedAt()).isEqualTo(8_000_999L);
  112. assertThat(saved.getStartedAt()).isNull();
  113. }
  114. @Test
  115. public void test_selectByUuid() {
  116. CeQueueDto ceQueueDto = insertPending(TASK_UUID_1, MAIN_COMPONENT_UUID_1);
  117. assertThat(underTest.selectByUuid(db.getSession(), "TASK_UNKNOWN").isPresent()).isFalse();
  118. CeQueueDto saved = underTest.selectByUuid(db.getSession(), TASK_UUID_1).get();
  119. assertThat(saved.getUuid()).isEqualTo(TASK_UUID_1);
  120. assertThat(saved.getTaskType()).isEqualTo(CeTaskTypes.REPORT);
  121. assertThat(saved.getMainComponentUuid()).isEqualTo(MAIN_COMPONENT_UUID_1);
  122. assertThat(saved.getComponentUuid()).isEqualTo(ceQueueDto.getComponentUuid());
  123. assertThat(saved.getStatus()).isEqualTo(PENDING);
  124. assertThat(saved.getSubmitterUuid()).isEqualTo("henri");
  125. assertThat(saved.getWorkerUuid()).isNull();
  126. assertThat(saved.getCreatedAt()).isEqualTo(INIT_TIME);
  127. assertThat(saved.getUpdatedAt()).isEqualTo(INIT_TIME);
  128. assertThat(saved.getStartedAt()).isNull();
  129. }
  130. @Test
  131. public void test_selectByMainComponentUuid() {
  132. insertPending(TASK_UUID_1, MAIN_COMPONENT_UUID_1);
  133. insertPending(TASK_UUID_2, MAIN_COMPONENT_UUID_1);
  134. insertPending(TASK_UUID_3, "PROJECT_2");
  135. assertThat(underTest.selectByMainComponentUuid(db.getSession(), "UNKNOWN")).isEmpty();
  136. assertThat(underTest.selectByMainComponentUuid(db.getSession(), MAIN_COMPONENT_UUID_1)).extracting("uuid").containsOnly(TASK_UUID_1, TASK_UUID_2);
  137. assertThat(underTest.selectByMainComponentUuid(db.getSession(), "PROJECT_2")).extracting("uuid").containsOnly(TASK_UUID_3);
  138. }
  139. @Test
  140. public void test_selectAllInAscOrder() {
  141. insertPending(TASK_UUID_1, MAIN_COMPONENT_UUID_1);
  142. insertPending(TASK_UUID_2, MAIN_COMPONENT_UUID_1);
  143. insertPending(TASK_UUID_3, "PROJECT_2");
  144. assertThat(underTest.selectAllInAscOrder(db.getSession())).extracting("uuid").containsOnly(TASK_UUID_1, TASK_UUID_2, TASK_UUID_3);
  145. }
  146. @Test
  147. public void selectPending_returns_pending_tasks() {
  148. insertPending("p1");
  149. insertPending("p2");
  150. insertPending("p3");
  151. makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1"));
  152. makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i2"));
  153. makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i3"));
  154. assertThat(underTest.selectPending(db.getSession()))
  155. .extracting(CeQueueDto::getUuid)
  156. .containsOnly("p1", "p2", "p3");
  157. }
  158. @Test
  159. public void selectCreationDateOfOldestPendingByMainComponentUuid_on_any_component_returns_date() {
  160. long time = alwaysIncreasingSystem2.now() + 10_000;
  161. insertPending("p1", dto -> {
  162. dto.setCreatedAt(time);
  163. dto.setUpdatedAt(time + 500);
  164. dto.setMainComponentUuid("c1");
  165. });
  166. insertPending("p2", dto -> {
  167. dto.setCreatedAt(time + 1000);
  168. dto.setUpdatedAt(time + 2000);
  169. dto.setMainComponentUuid("c2");
  170. });
  171. makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1", dto -> dto.setMainComponentUuid("c3")));
  172. assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), null))
  173. .isEqualTo(Optional.of(time));
  174. }
  175. @Test
  176. public void selectCreationDateOfOldestPendingByMainComponentUuid_on_specific_component_returns_date() {
  177. long time = alwaysIncreasingSystem2.now() + 10_000;
  178. insertPending("p1", dto -> {
  179. dto.setCreatedAt(time);
  180. dto.setUpdatedAt(time + 500);
  181. dto.setMainComponentUuid("c2");
  182. });
  183. insertPending("p2", dto -> {
  184. dto.setCreatedAt(time + 2000);
  185. dto.setUpdatedAt(time + 3000);
  186. dto.setMainComponentUuid("c1");
  187. });
  188. insertPending("p3", dto -> {
  189. dto.setCreatedAt(time + 4000);
  190. dto.setUpdatedAt(time + 5000);
  191. dto.setMainComponentUuid("c1");
  192. });
  193. makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1", dto -> dto.setMainComponentUuid("c1")));
  194. assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), "c1"))
  195. .isEqualTo(Optional.of(time + 2000));
  196. }
  197. @Test
  198. public void selectCreationDateOfOldestPendingByMainComponentUuid_returns_empty_when_no_pending_tasks() {
  199. makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1"));
  200. assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), null))
  201. .isEmpty();
  202. }
  203. @Test
  204. public void selectWornout_returns_task_pending_with_a_non_null_startedAt() {
  205. insertPending("p1");
  206. makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1"));
  207. CeQueueDto resetDto = makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i2"));
  208. makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i3"));
  209. reset(db.getSession(), alwaysIncreasingSystem2.now(), resetDto);
  210. List<CeQueueDto> ceQueueDtos = underTest.selectWornout(db.getSession());
  211. assertThat(ceQueueDtos)
  212. .extracting(CeQueueDto::getStatus, CeQueueDto::getUuid)
  213. .containsOnly(tuple(PENDING, resetDto.getUuid()));
  214. }
  215. @Test
  216. public void test_delete() {
  217. insertPending(TASK_UUID_1, MAIN_COMPONENT_UUID_1);
  218. insertPending(TASK_UUID_2, MAIN_COMPONENT_UUID_1);
  219. int deletedCount = underTest.deleteByUuid(db.getSession(), "UNKNOWN");
  220. assertThat(deletedCount).isZero();
  221. assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1)).isPresent();
  222. deletedCount = underTest.deleteByUuid(db.getSession(), TASK_UUID_1);
  223. assertThat(deletedCount).isEqualTo(1);
  224. assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1)).isEmpty();
  225. deletedCount = underTest.deleteByUuid(db.getSession(), TASK_UUID_2, null);
  226. assertThat(deletedCount).isEqualTo(1);
  227. assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_2)).isEmpty();
  228. }
  229. @Test
  230. public void test_delete_with_expected_status() {
  231. insertPending(TASK_UUID_1, MAIN_COMPONENT_UUID_1);
  232. insertInProgress(TASK_UUID_2);
  233. int deletedCount = underTest.deleteByUuid(db.getSession(), "UNKNOWN", null);
  234. assertThat(deletedCount).isZero();
  235. assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1)).isPresent();
  236. deletedCount = underTest.deleteByUuid(db.getSession(), TASK_UUID_1, new DeleteIf(IN_PROGRESS));
  237. assertThat(deletedCount).isZero();
  238. assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1)).isPresent();
  239. deletedCount = underTest.deleteByUuid(db.getSession(), TASK_UUID_2, new DeleteIf(PENDING));
  240. assertThat(deletedCount).isZero();
  241. assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_2)).isPresent();
  242. deletedCount = underTest.deleteByUuid(db.getSession(), TASK_UUID_1, new DeleteIf(PENDING));
  243. assertThat(deletedCount).isEqualTo(1);
  244. assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1)).isEmpty();
  245. deletedCount = underTest.deleteByUuid(db.getSession(), TASK_UUID_2, new DeleteIf(IN_PROGRESS));
  246. assertThat(deletedCount).isEqualTo(1);
  247. assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_2)).isEmpty();
  248. }
  249. @Test
  250. public void resetToPendingForWorker_resets_status_of_non_pending_tasks_only_for_specified_workerUuid() {
  251. CeQueueDto[] worker1 = {insertPending("u1"), insertPending("u2"), insertPending("u3"), insertPending("u4")};
  252. CeQueueDto[] worker2 = {insertPending("o1"), insertPending("o2"), insertPending("o3"), insertPending("o4")};
  253. long startedAt = alwaysIncreasingSystem2.now();
  254. makeInProgress(WORKER_UUID_1, startedAt, worker1[0]);
  255. makeInProgress(WORKER_UUID_1, startedAt, worker1[3]);
  256. makeInProgress(WORKER_UUID_2, startedAt, worker2[0]);
  257. makeInProgress(WORKER_UUID_2, startedAt, worker2[3]);
  258. underTestAlwaysIncreasingSystem2.resetToPendingForWorker(db.getSession(), WORKER_UUID_1);
  259. verifyResetToPendingForWorker(worker1[0], WORKER_UUID_1, startedAt);
  260. verifyUnchangedByResetToPendingForWorker(worker1[1]);
  261. verifyUnchangedByResetToPendingForWorker(worker1[2]);
  262. verifyResetToPendingForWorker(worker1[3], WORKER_UUID_1, startedAt);
  263. verifyInProgressUnchangedByResetToPendingForWorker(worker2[0], WORKER_UUID_2, startedAt);
  264. verifyUnchangedByResetToPendingForWorker(worker2[1]);
  265. verifyUnchangedByResetToPendingForWorker(worker2[2]);
  266. verifyInProgressUnchangedByResetToPendingForWorker(worker2[3], WORKER_UUID_2, startedAt);
  267. }
  268. @Test
  269. public void resetTasksWithUnknownWorkerUUIDs_with_empty_set_resets_status_of_all_pending_tasks() {
  270. CeQueueDto[] worker1 = {insertPending("u1"), insertPending("u2"), insertPending("u3"), insertPending("u4")};
  271. CeQueueDto[] worker2 = {insertPending("o1"), insertPending("o2"), insertPending("o3"), insertPending("o4")};
  272. long startedAt = alwaysIncreasingSystem2.now();
  273. makeInProgress(WORKER_UUID_1, startedAt, worker1[0]);
  274. makeInProgress(WORKER_UUID_1, startedAt, worker1[3]);
  275. makeInProgress(WORKER_UUID_2, startedAt, worker2[0]);
  276. makeInProgress(WORKER_UUID_2, startedAt, worker2[3]);
  277. underTestAlwaysIncreasingSystem2.resetTasksWithUnknownWorkerUUIDs(db.getSession(), ImmutableSet.of());
  278. verifyResetByResetTasks(worker1[0], startedAt);
  279. verifyUnchangedByResetToPendingForWorker(worker1[1]);
  280. verifyUnchangedByResetToPendingForWorker(worker1[2]);
  281. verifyResetByResetTasks(worker1[3], startedAt);
  282. verifyResetByResetTasks(worker2[0], startedAt);
  283. verifyUnchangedByResetToPendingForWorker(worker2[1]);
  284. verifyUnchangedByResetToPendingForWorker(worker2[2]);
  285. verifyResetByResetTasks(worker2[3], startedAt);
  286. }
  287. @Test
  288. public void resetTasksWithUnknownWorkerUUIDs_set_resets_status_of_all_pending_tasks_with_unknown_workers() {
  289. CeQueueDto[] worker1 = {insertPending("u1"), insertPending("u2"), insertPending("u3"), insertPending("u4")};
  290. CeQueueDto[] worker2 = {insertPending("o1"), insertPending("o2"), insertPending("o3"), insertPending("o4")};
  291. long startedAt = alwaysIncreasingSystem2.now();
  292. makeInProgress(WORKER_UUID_1, startedAt, worker1[0]);
  293. makeInProgress(WORKER_UUID_1, startedAt, worker1[3]);
  294. makeInProgress(WORKER_UUID_2, startedAt, worker2[0]);
  295. makeInProgress(WORKER_UUID_2, startedAt, worker2[3]);
  296. underTestAlwaysIncreasingSystem2.resetTasksWithUnknownWorkerUUIDs(db.getSession(), ImmutableSet.of(WORKER_UUID_1, "unknown"));
  297. verifyInProgressUnchangedByResetToPendingForWorker(worker1[0], WORKER_UUID_1, startedAt);
  298. verifyUnchangedByResetToPendingForWorker(worker1[1]);
  299. verifyUnchangedByResetToPendingForWorker(worker1[2]);
  300. verifyInProgressUnchangedByResetToPendingForWorker(worker1[3], WORKER_UUID_1, startedAt);
  301. verifyResetByResetTasks(worker2[0], startedAt);
  302. verifyUnchangedByResetToPendingForWorker(worker2[1]);
  303. verifyUnchangedByResetToPendingForWorker(worker2[2]);
  304. verifyResetByResetTasks(worker2[3], startedAt);
  305. }
  306. private CeQueueDto makeInProgress(String workerUuid, long startedAt, CeQueueDto ceQueueDto) {
  307. CeQueueTesting.makeInProgress(db.getSession(), workerUuid, startedAt, ceQueueDto);
  308. return underTestAlwaysIncreasingSystem2.selectByUuid(db.getSession(), ceQueueDto.getUuid()).get();
  309. }
  310. private void verifyResetByResetTasks(CeQueueDto original, long startedAt) {
  311. CeQueueDto dto = db.getDbClient().ceQueueDao().selectByUuid(db.getSession(), original.getUuid()).get();
  312. assertThat(dto.getStatus()).isEqualTo(PENDING);
  313. assertThat(dto.getStartedAt()).isEqualTo(startedAt);
  314. assertThat(dto.getCreatedAt()).isEqualTo(original.getCreatedAt());
  315. assertThat(dto.getUpdatedAt()).isGreaterThan(startedAt);
  316. assertThat(dto.getWorkerUuid()).isNull();
  317. }
  318. private void verifyResetToPendingForWorker(CeQueueDto original, String workerUuid, long startedAt) {
  319. CeQueueDto dto = db.getDbClient().ceQueueDao().selectByUuid(db.getSession(), original.getUuid()).get();
  320. assertThat(dto.getStatus()).isEqualTo(PENDING);
  321. assertThat(dto.getStartedAt()).isEqualTo(startedAt);
  322. assertThat(dto.getCreatedAt()).isEqualTo(original.getCreatedAt());
  323. assertThat(dto.getUpdatedAt()).isGreaterThan(startedAt);
  324. assertThat(dto.getWorkerUuid()).isEqualTo(workerUuid);
  325. }
  326. private void verifyUnchangedByResetToPendingForWorker(CeQueueDto original) {
  327. CeQueueDto dto = db.getDbClient().ceQueueDao().selectByUuid(db.getSession(), original.getUuid()).get();
  328. assertThat(dto.getStatus()).isEqualTo(original.getStatus());
  329. assertThat(dto.getStartedAt()).isEqualTo(original.getStartedAt());
  330. assertThat(dto.getCreatedAt()).isEqualTo(original.getCreatedAt());
  331. assertThat(dto.getUpdatedAt()).isEqualTo(original.getUpdatedAt());
  332. assertThat(dto.getWorkerUuid()).isEqualTo(original.getWorkerUuid());
  333. }
  334. private void verifyInProgressUnchangedByResetToPendingForWorker(CeQueueDto original, String workerUuid, long startedAt) {
  335. CeQueueDto dto = db.getDbClient().ceQueueDao().selectByUuid(db.getSession(), original.getUuid()).get();
  336. assertThat(dto.getStatus()).isEqualTo(IN_PROGRESS);
  337. assertThat(dto.getStartedAt()).isEqualTo(startedAt);
  338. assertThat(dto.getCreatedAt()).isEqualTo(original.getCreatedAt());
  339. assertThat(dto.getUpdatedAt()).isEqualTo(startedAt);
  340. assertThat(dto.getWorkerUuid()).isEqualTo(workerUuid);
  341. }
  342. @Test
  343. public void peek_none_if_no_pendings() {
  344. assertThat(underTest.peek(db.getSession(), WORKER_UUID_1, false, false)).isNotPresent();
  345. // not pending, but in progress
  346. makeInProgress(WORKER_UUID_1, 2_232_222L, insertPending(TASK_UUID_1, MAIN_COMPONENT_UUID_1));
  347. assertThat(underTest.peek(db.getSession(), WORKER_UUID_1, false, false)).isNotPresent();
  348. }
  349. @Test
  350. public void peek_oldest_pending() {
  351. insertPending(TASK_UUID_1, MAIN_COMPONENT_UUID_1);
  352. system2.setNow(INIT_TIME + 3_000_000);
  353. insertPending(TASK_UUID_2, MAIN_COMPONENT_UUID_2);
  354. assertThat(db.countRowsOfTable("ce_queue")).isEqualTo(2);
  355. verifyCeQueueStatuses(TASK_UUID_1, PENDING, TASK_UUID_2, PENDING);
  356. // peek first one
  357. Optional<CeQueueDto> peek = underTest.peek(db.getSession(), WORKER_UUID_1, false, false);
  358. assertThat(peek).isPresent();
  359. assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_1);
  360. assertThat(peek.get().getStatus()).isEqualTo(IN_PROGRESS);
  361. assertThat(peek.get().getWorkerUuid()).isEqualTo(WORKER_UUID_1);
  362. verifyCeQueueStatuses(TASK_UUID_1, IN_PROGRESS, TASK_UUID_2, PENDING);
  363. // peek second one
  364. peek = underTest.peek(db.getSession(), WORKER_UUID_2, false, false);
  365. assertThat(peek).isPresent();
  366. assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_2);
  367. assertThat(peek.get().getStatus()).isEqualTo(IN_PROGRESS);
  368. assertThat(peek.get().getWorkerUuid()).isEqualTo(WORKER_UUID_2);
  369. verifyCeQueueStatuses(TASK_UUID_1, IN_PROGRESS, TASK_UUID_2, IN_PROGRESS);
  370. // no more pendings
  371. assertThat(underTest.peek(db.getSession(), WORKER_UUID_1, false, false)).isNotPresent();
  372. }
  373. @Test
  374. public void do_not_peek_multiple_tasks_on_same_main_component_at_the_same_time() {
  375. // two pending tasks on the same project
  376. insertPending(TASK_UUID_1, MAIN_COMPONENT_UUID_1);
  377. system2.setNow(INIT_TIME + 3_000_000);
  378. insertPending(TASK_UUID_2, MAIN_COMPONENT_UUID_1);
  379. Optional<CeQueueDto> peek = underTest.peek(db.getSession(), WORKER_UUID_1, false, false);
  380. assertThat(peek).isPresent();
  381. assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_1);
  382. assertThat(peek.get().getMainComponentUuid()).isEqualTo(MAIN_COMPONENT_UUID_1);
  383. assertThat(peek.get().getWorkerUuid()).isEqualTo(WORKER_UUID_1);
  384. verifyCeQueueStatuses(TASK_UUID_1, IN_PROGRESS, TASK_UUID_2, PENDING);
  385. // do not peek second task as long as the first one is in progress
  386. peek = underTest.peek(db.getSession(), WORKER_UUID_1, false, false);
  387. assertThat(peek.isPresent()).isFalse();
  388. // first one is finished
  389. underTest.deleteByUuid(db.getSession(), TASK_UUID_1);
  390. peek = underTest.peek(db.getSession(), WORKER_UUID_2, false, false);
  391. assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_2);
  392. assertThat(peek.get().getWorkerUuid()).isEqualTo(WORKER_UUID_2);
  393. }
  394. @Test
  395. public void select_by_query() {
  396. // task status not in query
  397. insertPending(newCeQueueDto(TASK_UUID_1)
  398. .setMainComponentUuid(MAIN_COMPONENT_UUID_1)
  399. .setStatus(IN_PROGRESS)
  400. .setTaskType(CeTaskTypes.REPORT)
  401. .setCreatedAt(100_000L));
  402. // too early
  403. insertPending(newCeQueueDto(TASK_UUID_3)
  404. .setMainComponentUuid(MAIN_COMPONENT_UUID_1)
  405. .setStatus(PENDING)
  406. .setTaskType(CeTaskTypes.REPORT)
  407. .setCreatedAt(90_000L));
  408. // task type not in query
  409. insertPending(newCeQueueDto("TASK_4")
  410. .setMainComponentUuid("PROJECT_2")
  411. .setStatus(PENDING)
  412. .setTaskType("ANOTHER_TYPE")
  413. .setCreatedAt(100_000L));
  414. // correct
  415. insertPending(newCeQueueDto(TASK_UUID_2)
  416. .setMainComponentUuid(MAIN_COMPONENT_UUID_1)
  417. .setStatus(PENDING)
  418. .setTaskType(CeTaskTypes.REPORT)
  419. .setCreatedAt(100_000L));
  420. // correct submitted later
  421. insertPending(newCeQueueDto("TASK_5")
  422. .setMainComponentUuid(MAIN_COMPONENT_UUID_1)
  423. .setStatus(PENDING)
  424. .setTaskType(CeTaskTypes.REPORT)
  425. .setCreatedAt(120_000L));
  426. // select by component uuid, status, task type and minimum submitted at
  427. CeTaskQuery query = new CeTaskQuery()
  428. .setMainComponentUuids(newArrayList(MAIN_COMPONENT_UUID_1, "PROJECT_2"))
  429. .setStatuses(singletonList(PENDING.name()))
  430. .setType(CeTaskTypes.REPORT)
  431. .setMinSubmittedAt(100_000L);
  432. List<CeQueueDto> result = underTest.selectByQueryInDescOrder(db.getSession(), query, 1_000);
  433. int total = underTest.countByQuery(db.getSession(), query);
  434. assertThat(result).extracting("uuid").containsExactly("TASK_5", TASK_UUID_2);
  435. assertThat(total).isEqualTo(2);
  436. }
  437. @Test
  438. public void select_by_query_returns_empty_list_when_only_current() {
  439. insertPending(newCeQueueDto(TASK_UUID_1)
  440. .setComponentUuid(MAIN_COMPONENT_UUID_1)
  441. .setStatus(IN_PROGRESS)
  442. .setTaskType(CeTaskTypes.REPORT)
  443. .setCreatedAt(100_000L));
  444. CeTaskQuery query = new CeTaskQuery().setOnlyCurrents(true);
  445. List<CeQueueDto> result = underTest.selectByQueryInDescOrder(db.getSession(), query, 1_000);
  446. int total = underTest.countByQuery(db.getSession(), query);
  447. assertThat(result).isEmpty();
  448. assertThat(total).isZero();
  449. }
  450. @Test
  451. public void select_by_query_returns_empty_list_when_max_submitted_at() {
  452. insertPending(newCeQueueDto(TASK_UUID_1)
  453. .setComponentUuid(MAIN_COMPONENT_UUID_1)
  454. .setStatus(IN_PROGRESS)
  455. .setTaskType(CeTaskTypes.REPORT)
  456. .setCreatedAt(100_000L));
  457. CeTaskQuery query = new CeTaskQuery().setMaxExecutedAt(1_000_000_000_000L);
  458. List<CeQueueDto> result = underTest.selectByQueryInDescOrder(db.getSession(), query, 1_000);
  459. int total = underTest.countByQuery(db.getSession(), query);
  460. assertThat(result).isEmpty();
  461. assertThat(total).isZero();
  462. }
  463. @Test
  464. public void select_by_query_returns_empty_list_when_empty_list_of_main_component_uuid() {
  465. insertPending(newCeQueueDto(TASK_UUID_1)
  466. .setComponentUuid(MAIN_COMPONENT_UUID_1)
  467. .setStatus(IN_PROGRESS)
  468. .setTaskType(CeTaskTypes.REPORT)
  469. .setCreatedAt(100_000L));
  470. CeTaskQuery query = new CeTaskQuery().setMainComponentUuids(Collections.emptyList());
  471. List<CeQueueDto> result = underTest.selectByQueryInDescOrder(db.getSession(), query, 1_000);
  472. int total = underTest.countByQuery(db.getSession(), query);
  473. assertThat(result).isEmpty();
  474. assertThat(total).isZero();
  475. }
  476. @Test
  477. public void count_by_status_and_main_component_uuid() {
  478. // task retrieved in the queue
  479. insertPending(newCeQueueDto(TASK_UUID_1)
  480. .setMainComponentUuid(MAIN_COMPONENT_UUID_1)
  481. .setStatus(IN_PROGRESS)
  482. .setTaskType(CeTaskTypes.REPORT)
  483. .setCreatedAt(100_000L));
  484. // on component uuid 2, not returned
  485. insertPending(newCeQueueDto(TASK_UUID_2)
  486. .setMainComponentUuid(MAIN_COMPONENT_UUID_2)
  487. .setStatus(IN_PROGRESS)
  488. .setTaskType(CeTaskTypes.REPORT)
  489. .setCreatedAt(100_000L));
  490. // pending status, not returned
  491. insertPending(newCeQueueDto(TASK_UUID_3)
  492. .setMainComponentUuid(MAIN_COMPONENT_UUID_1)
  493. .setStatus(PENDING)
  494. .setTaskType(CeTaskTypes.REPORT)
  495. .setCreatedAt(100_000L));
  496. assertThat(underTest.countByStatusAndMainComponentUuid(db.getSession(), IN_PROGRESS, MAIN_COMPONENT_UUID_1)).isEqualTo(1);
  497. assertThat(underTest.countByStatus(db.getSession(), IN_PROGRESS)).isEqualTo(2);
  498. }
  499. @Test
  500. public void count_by_status_and_main_component_uuids() {
  501. // task retrieved in the queue
  502. insertPending(newCeQueueDto(TASK_UUID_1)
  503. .setMainComponentUuid(MAIN_COMPONENT_UUID_1)
  504. .setStatus(IN_PROGRESS)
  505. .setTaskType(CeTaskTypes.REPORT)
  506. .setCreatedAt(100_000L));
  507. // on component uuid 2, not returned
  508. insertPending(newCeQueueDto(TASK_UUID_2)
  509. .setMainComponentUuid(MAIN_COMPONENT_UUID_2)
  510. .setStatus(IN_PROGRESS)
  511. .setTaskType(CeTaskTypes.REPORT)
  512. .setCreatedAt(100_000L));
  513. // pending status, not returned
  514. insertPending(newCeQueueDto(TASK_UUID_3)
  515. .setMainComponentUuid(MAIN_COMPONENT_UUID_1)
  516. .setStatus(PENDING)
  517. .setTaskType(CeTaskTypes.REPORT)
  518. .setCreatedAt(100_000L));
  519. assertThat(underTest.countByStatusAndMainComponentUuids(db.getSession(), IN_PROGRESS, ImmutableSet.of())).isEmpty();
  520. assertThat(underTest.countByStatusAndMainComponentUuids(db.getSession(), IN_PROGRESS, ImmutableSet.of("non existing component uuid"))).isEmpty();
  521. assertThat(underTest.countByStatusAndMainComponentUuids(db.getSession(), IN_PROGRESS, ImmutableSet.of(MAIN_COMPONENT_UUID_1, MAIN_COMPONENT_UUID_2)))
  522. .containsOnly(entry(MAIN_COMPONENT_UUID_1, 1), entry(MAIN_COMPONENT_UUID_2, 1));
  523. assertThat(underTest.countByStatusAndMainComponentUuids(db.getSession(), PENDING, ImmutableSet.of(MAIN_COMPONENT_UUID_1, MAIN_COMPONENT_UUID_2)))
  524. .containsOnly(entry(MAIN_COMPONENT_UUID_1, 1));
  525. assertThat(underTest.countByStatus(db.getSession(), IN_PROGRESS)).isEqualTo(2);
  526. }
  527. @Test
  528. public void selectInProgressStartedBefore() {
  529. // pending task is ignored
  530. insertPending(newCeQueueDto(TASK_UUID_1)
  531. .setStatus(PENDING)
  532. .setStartedAt(1_000L));
  533. // in-progress tasks
  534. insertPending(newCeQueueDto(TASK_UUID_2)
  535. .setStatus(IN_PROGRESS)
  536. .setStartedAt(1_000L));
  537. insertPending(newCeQueueDto(TASK_UUID_3)
  538. .setStatus(IN_PROGRESS)
  539. .setStartedAt(2_000L));
  540. assertThat(underTest.selectInProgressStartedBefore(db.getSession(), 500L)).isEmpty();
  541. assertThat(underTest.selectInProgressStartedBefore(db.getSession(), 1_000L)).isEmpty();
  542. assertThat(underTest.selectInProgressStartedBefore(db.getSession(), 1_500L)).extracting(CeQueueDto::getUuid).containsExactly(TASK_UUID_2);
  543. assertThat(underTest.selectInProgressStartedBefore(db.getSession(), 3_000L)).extracting(CeQueueDto::getUuid).containsExactlyInAnyOrder(TASK_UUID_2, TASK_UUID_3);
  544. }
  545. @Test
  546. public void exclude_portfolios_computation_when_indexing_issues() {
  547. insertBranch(MAIN_COMPONENT_UUID_1);
  548. insertPending(newCeQueueDto(TASK_UUID_1)
  549. .setComponentUuid(MAIN_COMPONENT_UUID_1)
  550. .setMainComponentUuid(MAIN_COMPONENT_UUID_1)
  551. .setStatus(PENDING)
  552. .setTaskType(CeTaskTypes.BRANCH_ISSUE_SYNC)
  553. .setCreatedAt(100_000L));
  554. String view_uuid = "view_uuid";
  555. insertView(view_uuid);
  556. insertPending(newCeQueueDto(TASK_UUID_2)
  557. .setComponentUuid(view_uuid)
  558. .setMainComponentUuid(view_uuid)
  559. .setStatus(PENDING)
  560. .setTaskType(CeTaskTypes.REPORT)
  561. .setCreatedAt(100_000L));
  562. Optional<CeQueueDto> peek = underTest.peek(db.getSession(), WORKER_UUID_1, false, true);
  563. assertThat(peek).isPresent();
  564. assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_1);
  565. Optional<CeQueueDto> peek2 = underTest.peek(db.getSession(), WORKER_UUID_1, false, false);
  566. assertThat(peek2).isPresent();
  567. assertThat(peek2.get().getUuid()).isEqualTo(TASK_UUID_2);
  568. }
  569. @Test
  570. public void excluding_view_pick_up_orphan_branches() {
  571. insertPending(newCeQueueDto(TASK_UUID_1)
  572. .setComponentUuid(MAIN_COMPONENT_UUID_1)
  573. .setMainComponentUuid("non-existing-uuid")
  574. .setStatus(PENDING)
  575. .setTaskType(CeTaskTypes.BRANCH_ISSUE_SYNC)
  576. .setCreatedAt(100_000L));
  577. Optional<CeQueueDto> peek = underTest.peek(db.getSession(), WORKER_UUID_1, false, true);
  578. assertThat(peek).isPresent();
  579. assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_1);
  580. }
  581. @Test
  582. public void hasAnyIssueSyncTaskPendingOrInProgress_PENDING() {
  583. assertThat(underTest.hasAnyIssueSyncTaskPendingOrInProgress(db.getSession())).isFalse();
  584. insertPending(newCeQueueDto(TASK_UUID_1)
  585. .setComponentUuid(MAIN_COMPONENT_UUID_1)
  586. .setStatus(PENDING)
  587. .setTaskType(CeTaskTypes.BRANCH_ISSUE_SYNC)
  588. .setCreatedAt(100_000L));
  589. assertThat(underTest.hasAnyIssueSyncTaskPendingOrInProgress(db.getSession())).isTrue();
  590. }
  591. @Test
  592. public void hasAnyIssueSyncTaskPendingOrInProgress_IN_PROGRESS() {
  593. assertThat(underTest.hasAnyIssueSyncTaskPendingOrInProgress(db.getSession())).isFalse();
  594. insertPending(newCeQueueDto(TASK_UUID_1)
  595. .setComponentUuid(MAIN_COMPONENT_UUID_1)
  596. .setStatus(IN_PROGRESS)
  597. .setTaskType(CeTaskTypes.BRANCH_ISSUE_SYNC)
  598. .setCreatedAt(100_000L));
  599. assertThat(underTest.hasAnyIssueSyncTaskPendingOrInProgress(db.getSession())).isTrue();
  600. }
  601. private void insertView(String view_uuid) {
  602. ComponentDto view = new ComponentDto();
  603. view.setQualifier("VW");
  604. view.setDbKey(view_uuid + "_key");
  605. view.setUuid(view_uuid);
  606. view.setPrivate(false);
  607. view.setRootUuid(view_uuid);
  608. view.setUuidPath("uuid_path");
  609. view.setProjectUuid(view_uuid);
  610. db.components().insertViewAndSnapshot(view);
  611. db.commit();
  612. }
  613. private void insertBranch(String uuid) {
  614. ComponentDto branch = new ComponentDto();
  615. branch.setQualifier("TRK");
  616. branch.setDbKey(uuid + "_key");
  617. branch.setUuid(uuid);
  618. branch.setPrivate(false);
  619. branch.setRootUuid(uuid);
  620. branch.setUuidPath("uuid_path");
  621. branch.setProjectUuid(uuid);
  622. db.components().insertComponent(branch);
  623. db.commit();
  624. }
  625. private void insertPending(CeQueueDto dto) {
  626. underTest.insert(db.getSession(), dto);
  627. db.commit();
  628. }
  629. private CeQueueDto insertPending(String uuid) {
  630. return insertPending(uuid, (Consumer<CeQueueDto>) null);
  631. }
  632. private CeQueueDto insertPending(String uuid, @Nullable Consumer<CeQueueDto> dtoConsumer) {
  633. CeQueueDto dto = new CeQueueDto();
  634. dto.setUuid(uuid);
  635. dto.setTaskType(CeTaskTypes.REPORT);
  636. dto.setStatus(PENDING);
  637. dto.setSubmitterUuid("henri");
  638. if (dtoConsumer != null) {
  639. dtoConsumer.accept(dto);
  640. }
  641. underTestAlwaysIncreasingSystem2.insert(db.getSession(), dto);
  642. db.getSession().commit();
  643. return dto;
  644. }
  645. private int pendingComponentUuidGenerator = new Random().nextInt(200);
  646. private CeQueueDto insertPending(String uuid, String mainComponentUuid) {
  647. CeQueueDto dto = new CeQueueDto();
  648. dto.setUuid(uuid);
  649. dto.setTaskType(CeTaskTypes.REPORT);
  650. dto.setMainComponentUuid(mainComponentUuid);
  651. dto.setComponentUuid("uuid_" + pendingComponentUuidGenerator++);
  652. dto.setStatus(PENDING);
  653. dto.setSubmitterUuid("henri");
  654. underTest.insert(db.getSession(), dto);
  655. db.getSession().commit();
  656. return dto;
  657. }
  658. private CeQueueDto insertInProgress(String uuid) {
  659. CeQueueDto ceQueueDto = insertPending(uuid);
  660. CeQueueTesting.makeInProgress(db.getSession(), "workerUuid", System2.INSTANCE.now(), ceQueueDto);
  661. return underTest.selectByUuid(db.getSession(), uuid).get();
  662. }
  663. private static Iterable<Map<String, Object>> upperizeKeys(List<Map<String, Object>> select) {
  664. return select.stream().map(new Function<Map<String, Object>, Map<String, Object>>() {
  665. @Nullable
  666. @Override
  667. public Map<String, Object> apply(Map<String, Object> input) {
  668. Map<String, Object> res = new HashMap<>(input.size());
  669. for (Map.Entry<String, Object> entry : input.entrySet()) {
  670. res.put(entry.getKey().toUpperCase(), entry.getValue());
  671. }
  672. return res;
  673. }
  674. }).collect(Collectors.toList());
  675. }
  676. private void verifyCeQueueStatuses(String taskUuid1, CeQueueDto.Status taskStatus1, String taskUuid2, CeQueueDto.Status taskStatus2) {
  677. verifyCeQueueStatuses(new String[] {taskUuid1, taskUuid2}, new CeQueueDto.Status[] {taskStatus1, taskStatus2});
  678. }
  679. private void verifyCeQueueStatuses(String[] taskUuids, CeQueueDto.Status[] statuses) {
  680. Map<String, Object>[] rows = new Map[taskUuids.length];
  681. for (int i = 0; i < taskUuids.length; i++) {
  682. rows[i] = rowMap(taskUuids[i], statuses[i]);
  683. }
  684. assertThat(upperizeKeys(db.select(SELECT_QUEUE_UUID_AND_STATUS_QUERY))).containsOnly(rows);
  685. }
  686. private static Map<String, Object> rowMap(String uuid, CeQueueDto.Status status) {
  687. return ImmutableMap.of("UUID", uuid, "STATUS", status.name());
  688. }
  689. private void mockSystem2ForSingleCall(long now) {
  690. Mockito.reset(mockedSystem2);
  691. when(mockedSystem2.now())
  692. .thenReturn(now)
  693. .thenThrow(new IllegalStateException("now should be called only once"));
  694. }
  695. }