@Before public void setUp() { memoryTaskManager = new MemoryTaskManager(); }
@Test public void getStatusShouldReturnWaitingWhenNotYetProcessed() { CountDownLatch task1Latch = new CountDownLatch(1); memoryTaskManager.submit(() -> { await(task1Latch); return Task.Result.COMPLETED; }); TaskId taskId = memoryTaskManager.submit(() -> Task.Result.COMPLETED); assertThat(memoryTaskManager.getExecutionDetails(taskId).getStatus()) .isEqualTo(TaskManager.Status.WAITING); }
@After public void tearDown() { memoryTaskManager.stop(); }
private void run(TaskExecutionDetails executionDetails, Task task, Consumer<TaskId> callback) { TaskExecutionDetails started = executionDetails.start(); idToExecutionDetails.put(started.getTaskId(), started); try { task.run() .onComplete(() -> success(started)) .onFailure(() -> failed(started, logger -> logger.info("Task was partially performed. Check logs for more details"))); } catch (Exception e) { failed(started, logger -> logger.error("Error while running task", executionDetails, e)); } finally { idToFuture.remove(executionDetails.getTaskId()); callback.accept(executionDetails.getTaskId()); } }
@Test public void getStatusShouldReturnFailedWhenExceptionThrown() { TaskId taskId = memoryTaskManager.submit(() -> { throw new RuntimeException(); }); memoryTaskManager.await(taskId); assertThat(memoryTaskManager.getExecutionDetails(taskId).getStatus()) .isEqualTo(TaskManager.Status.FAILED); }
@Test public void listShouldAllowToSeeSuccessfulTasks() throws Exception { CountDownLatch latch1 = new CountDownLatch(1); CountDownLatch latch2 = new CountDownLatch(1); CountDownLatch latch3 = new CountDownLatch(1); memoryTaskManager.submit( () -> Task.Result.PARTIAL); memoryTaskManager.submit( () -> Task.Result.COMPLETED); TaskId inProgressId = memoryTaskManager.submit( () -> { await(latch1); latch2.countDown(); await(latch3); return Task.Result.COMPLETED; }); memoryTaskManager.submit( () -> { await(latch3); latch2.countDown(); return Task.Result.COMPLETED; }); latch1.countDown(); latch2.await(); assertThat(memoryTaskManager.list(TaskManager.Status.IN_PROGRESS)) .extracting(TaskExecutionDetails::getTaskId) .containsOnly(inProgressId); }
@Override public TaskId submit(Task task) { return submit(task, id -> { }); }
@Test public void getStatusShouldReturnCancelledWhenCancelled() throws Exception { CountDownLatch task1Latch = new CountDownLatch(1); CountDownLatch ensureStartedLatch = new CountDownLatch(1); CountDownLatch ensureFinishedLatch = new CountDownLatch(1); TaskId id = memoryTaskManager.submit(() -> { ensureStartedLatch.countDown(); await(task1Latch); return Task.Result.COMPLETED; }, any -> ensureFinishedLatch.countDown()); ensureStartedLatch.await(); memoryTaskManager.cancel(id); ensureFinishedLatch.await(); assertThat(memoryTaskManager.getExecutionDetails(id).getStatus()) .isEqualTo(TaskManager.Status.CANCELLED); }
@Test public void taskCodeAfterCancelIsNotRun() { CountDownLatch task1Latch = new CountDownLatch(1); AtomicInteger count = new AtomicInteger(0); TaskId id = memoryTaskManager.submit(() -> { await(task1Latch); count.incrementAndGet(); return Task.Result.COMPLETED; }); memoryTaskManager.cancel(id); task1Latch.countDown(); assertThat(count.get()).isEqualTo(0); }
@Override public TaskExecutionDetails await(TaskId id) { Optional.ofNullable(idToFuture.get(id)) .ifPresent(Throwing.consumer(Future::get)); return getExecutionDetails(id); }
@Test public void listCancelledShouldBeEmptyWhenNoTasks() throws Exception { assertThat(memoryTaskManager.list(TaskManager.Status.CANCELLED)).isEmpty(); }
private void runWithMdc(TaskExecutionDetails executionDetails, Task task, Consumer<TaskId> callback) { MDCBuilder.withMdc( MDCBuilder.create() .addContext(Task.TASK_ID, executionDetails.getTaskId()) .addContext(Task.TASK_TYPE, executionDetails.getType()) .addContext(Task.TASK_DETAILS, executionDetails.getAdditionalInformation()), () -> run(executionDetails, task, callback)); }
@Test public void listShouldAllowToSeeInProgressTasks() throws Exception { CountDownLatch latch1 = new CountDownLatch(1); CountDownLatch latch2 = new CountDownLatch(1); CountDownLatch latch3 = new CountDownLatch(1); memoryTaskManager.submit( () -> Task.Result.PARTIAL); TaskId successfulId = memoryTaskManager.submit( () -> Task.Result.COMPLETED); memoryTaskManager.submit( () -> { await(latch1); latch2.countDown(); await(latch3); return Task.Result.COMPLETED; }); memoryTaskManager.submit( () -> { await(latch3); latch2.countDown(); return Task.Result.COMPLETED; }); latch1.countDown(); latch2.await(); assertThat(memoryTaskManager.list(TaskManager.Status.COMPLETED)) .extracting(TaskExecutionDetails::getTaskId) .containsOnly(successfulId); }
@Test public void listShouldReturnTaskDetailsWhenTaskInProgress() throws Exception { CountDownLatch taskInProgressLatch = new CountDownLatch(1); TaskId taskId = taskManager.submit(() -> { taskInProgressLatch.countDown(); await(); return Task.Result.COMPLETED; }); taskInProgressLatch.await(); when() .get() .then() .statusCode(HttpStatus.OK_200) .body("", hasSize(1)) .body("[0].status", is(TaskManager.Status.IN_PROGRESS.getValue())) .body("[0].taskId", is(taskId.getValue().toString())) .body("[0].class", is(not(empty()))); }
@Test public void getStatusShouldReturnFailedWhenExceptionThrown() { TaskId taskId = memoryTaskManager.submit(() -> { throw new RuntimeException(); }); memoryTaskManager.await(taskId); assertThat(memoryTaskManager.getExecutionDetails(taskId).getStatus()) .isEqualTo(TaskManager.Status.FAILED); }
@Test public void getStatusShouldReturnCancelledWhenCancelled() throws Exception { CountDownLatch task1Latch = new CountDownLatch(1); CountDownLatch ensureStartedLatch = new CountDownLatch(1); CountDownLatch ensureFinishedLatch = new CountDownLatch(1); TaskId id = memoryTaskManager.submit(() -> { ensureStartedLatch.countDown(); await(task1Latch); return Task.Result.COMPLETED; }, any -> ensureFinishedLatch.countDown()); ensureStartedLatch.await(); memoryTaskManager.cancel(id); ensureFinishedLatch.await(); assertThat(memoryTaskManager.getExecutionDetails(id).getStatus()) .isEqualTo(TaskManager.Status.CANCELLED); }
@Test public void taskCodeAfterCancelIsNotRun() { CountDownLatch task1Latch = new CountDownLatch(1); AtomicInteger count = new AtomicInteger(0); TaskId id = memoryTaskManager.submit(() -> { await(task1Latch); count.incrementAndGet(); return Task.Result.COMPLETED; }); memoryTaskManager.cancel(id); task1Latch.countDown(); assertThat(count.get()).isEqualTo(0); }
@Test public void getStatusShouldReturnUnknownWhenUnknownId() { TaskId unknownId = TaskId.generateTaskId(); assertThatThrownBy(() -> memoryTaskManager.getExecutionDetails(unknownId)) .isInstanceOf(TaskNotFoundException.class); }