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 31KB

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