Search in sources :

Example 1 with IN_PROGRESS

use of com.netflix.conductor.common.metadata.tasks.Task.Status.IN_PROGRESS in project conductor by Netflix.

the class AbstractWorkflowServiceTest method testSimpleWorkflowWithResponseTimeout.

@Test
public void testSimpleWorkflowWithResponseTimeout() throws Exception {
    createWFWithResponseTimeout();
    String correlationId = "unit_test_1";
    Map<String, Object> workflowInput = new HashMap<>();
    String inputParam1 = "p1 value";
    workflowInput.put("param1", inputParam1);
    workflowInput.put("param2", "p2 value");
    String workflowId = startOrLoadWorkflowExecution("RTOWF", 1, correlationId, workflowInput, null, null);
    logger.debug("testSimpleWorkflowWithResponseTimeout.wfid=" + workflowId);
    assertNotNull(workflowId);
    Workflow workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    assertEquals(RUNNING, workflow.getStatus());
    // The very first task is the one that should be scheduled.
    assertEquals(1, workflow.getTasks().size());
    assertEquals(1, queueDAO.getSize("task_rt"));
    // Polling for the first task should return the first task
    Task task = workflowExecutionService.poll("task_rt", "task1.junit.worker.testTimeout");
    assertNotNull(task);
    assertEquals("task_rt", task.getTaskType());
    assertTrue(workflowExecutionService.ackTaskReceived(task.getTaskId()));
    assertEquals(workflowId, task.getWorkflowInstanceId());
    // As the task_rt is out of the queue, the next poll should not get it
    Task nullTask = workflowExecutionService.poll("task_rt", "task1.junit.worker.testTimeout");
    assertNull(nullTask);
    Thread.sleep(10000);
    workflowExecutor.decide(workflowId);
    assertEquals(1, queueDAO.getSize("task_rt"));
    // The first task would be timed_out and a new task will be scheduled
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    assertEquals(RUNNING, workflow.getStatus());
    assertEquals(2, workflow.getTasks().size());
    assertTrue(workflow.getTasks().stream().allMatch(t -> t.getReferenceTaskName().equals("task_rt_t1")));
    assertEquals(TIMED_OUT, workflow.getTasks().get(0).getStatus());
    assertEquals(SCHEDULED, workflow.getTasks().get(1).getStatus());
    // Polling now should get the same task back because it should have been put back in the queue
    Task taskAgain = workflowExecutionService.poll("task_rt", "task1.junit.worker");
    assertNotNull(taskAgain);
    // update task with callback after seconds greater than the response timeout
    taskAgain.setStatus(IN_PROGRESS);
    taskAgain.setCallbackAfterSeconds(2);
    workflowExecutionService.updateTask(taskAgain);
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    assertEquals(WorkflowStatus.RUNNING, workflow.getStatus());
    assertEquals(2, workflow.getTasks().size());
    assertEquals(SCHEDULED, workflow.getTasks().get(1).getStatus());
    // wait for callback after seconds which is longer than response timeout seconds and then call decide
    Thread.sleep(2010);
    // Ensure unacks are processed.
    queueDAO.processUnacks(taskAgain.getTaskDefName());
    workflowExecutor.decide(workflowId);
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    // Poll for task again
    taskAgain = workflowExecutionService.poll("task_rt", "task1.junit.worker");
    assertNotNull(taskAgain);
    taskAgain.getOutputData().put("op", "task1.Done");
    taskAgain.setStatus(COMPLETED);
    workflowExecutionService.updateTask(taskAgain);
    // poll for next task
    task = workflowExecutionService.poll("junit_task_2", "task2.junit.worker.testTimeout");
    assertNotNull(task);
    assertEquals("junit_task_2", task.getTaskType());
    assertTrue(workflowExecutionService.ackTaskReceived(task.getTaskId()));
    task.setStatus(COMPLETED);
    task.setReasonForIncompletion("unit test failure");
    workflowExecutionService.updateTask(task);
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    assertEquals(WorkflowStatus.COMPLETED, workflow.getStatus());
}
Also used : TaskUtils(com.netflix.conductor.common.utils.TaskUtils) MethodSorters(org.junit.runners.MethodSorters) SubWorkflow(com.netflix.conductor.core.execution.tasks.SubWorkflow) Arrays(java.util.Arrays) TimeoutPolicy(com.netflix.conductor.common.metadata.tasks.TaskDef.TimeoutPolicy) TEMP_FILE_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.TEMP_FILE_PATH) LoggerFactory(org.slf4j.LoggerFactory) Task(com.netflix.conductor.common.metadata.tasks.Task) StringUtils(org.apache.commons.lang3.StringUtils) Future(java.util.concurrent.Future) COMPLETED_WITH_ERRORS(com.netflix.conductor.common.metadata.tasks.Task.Status.COMPLETED_WITH_ERRORS) RerunWorkflowRequest(com.netflix.conductor.common.metadata.workflow.RerunWorkflowRequest) Workflow(com.netflix.conductor.common.run.Workflow) IN_PROGRESS(com.netflix.conductor.common.metadata.tasks.Task.Status.IN_PROGRESS) Map(java.util.Map) After(org.junit.After) PollData(com.netflix.conductor.common.metadata.tasks.PollData) WorkflowExecutor(com.netflix.conductor.core.execution.WorkflowExecutor) TASK_OUTPUT_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.TASK_OUTPUT_PATH) Terminate(com.netflix.conductor.core.execution.tasks.Terminate) WorkflowRepairService(com.netflix.conductor.core.execution.WorkflowRepairService) TaskDef(com.netflix.conductor.common.metadata.tasks.TaskDef) WorkflowStatus(com.netflix.conductor.common.run.Workflow.WorkflowStatus) MetadataMapperService(com.netflix.conductor.core.metadata.MetadataMapperService) Predicate(java.util.function.Predicate) Set(java.util.Set) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) Executors(java.util.concurrent.Executors) SCHEDULED(com.netflix.conductor.common.metadata.tasks.Task.Status.SCHEDULED) QueueDAO(com.netflix.conductor.dao.QueueDAO) INPUT_PAYLOAD_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.INPUT_PAYLOAD_PATH) List(java.util.List) DynamicForkJoinTaskList(com.netflix.conductor.common.metadata.workflow.DynamicForkJoinTaskList) Assert.assertFalse(org.junit.Assert.assertFalse) TIMED_OUT(com.netflix.conductor.common.metadata.tasks.Task.Status.TIMED_OUT) COMPLETED(com.netflix.conductor.common.metadata.tasks.Task.Status.COMPLETED) ExecutionService(com.netflix.conductor.service.ExecutionService) FixMethodOrder(org.junit.FixMethodOrder) JsonMapperProvider(com.netflix.conductor.common.utils.JsonMapperProvider) MetadataService(com.netflix.conductor.service.MetadataService) WorkflowContext(com.netflix.conductor.core.WorkflowContext) BeforeClass(org.junit.BeforeClass) SubWorkflowParams(com.netflix.conductor.common.metadata.workflow.SubWorkflowParams) Status(com.netflix.conductor.common.metadata.tasks.Task.Status) HashMap(java.util.HashMap) TaskResult(com.netflix.conductor.common.metadata.tasks.TaskResult) Inject(javax.inject.Inject) SUB_WORKFLOW(com.netflix.conductor.common.metadata.workflow.TaskType.SUB_WORKFLOW) LinkedList(java.util.LinkedList) ExpectedException(org.junit.rules.ExpectedException) RUNNING(com.netflix.conductor.common.run.Workflow.WorkflowStatus.RUNNING) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) TERMINATED(com.netflix.conductor.common.run.Workflow.WorkflowStatus.TERMINATED) INITIAL_WORKFLOW_INPUT_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.INITIAL_WORKFLOW_INPUT_PATH) ApplicationException(com.netflix.conductor.core.execution.ApplicationException) Uninterruptibles(com.google.common.util.concurrent.Uninterruptibles) Logger(org.slf4j.Logger) WorkflowSweeper(com.netflix.conductor.core.execution.WorkflowSweeper) Assert.assertNotNull(org.junit.Assert.assertNotNull) UserTask(com.netflix.conductor.tests.utils.UserTask) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Assert.assertTrue(org.junit.Assert.assertTrue) WorkflowDef(com.netflix.conductor.common.metadata.workflow.WorkflowDef) FileOutputStream(java.io.FileOutputStream) Test(org.junit.Test) FAILED(com.netflix.conductor.common.metadata.tasks.Task.Status.FAILED) WORKFLOW_OUTPUT_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.WORKFLOW_OUTPUT_PATH) TimeUnit(java.util.concurrent.TimeUnit) DECISION(com.netflix.conductor.common.metadata.workflow.TaskType.DECISION) Assert.assertNull(org.junit.Assert.assertNull) Rule(org.junit.Rule) Ignore(org.junit.Ignore) RetryLogic(com.netflix.conductor.common.metadata.tasks.TaskDef.RetryLogic) TaskType(com.netflix.conductor.common.metadata.workflow.TaskType) Collections(java.util.Collections) Assert.assertEquals(org.junit.Assert.assertEquals) Task(com.netflix.conductor.common.metadata.tasks.Task) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) UserTask(com.netflix.conductor.tests.utils.UserTask) HashMap(java.util.HashMap) SubWorkflow(com.netflix.conductor.core.execution.tasks.SubWorkflow) Workflow(com.netflix.conductor.common.run.Workflow) Test(org.junit.Test)

Example 2 with IN_PROGRESS

use of com.netflix.conductor.common.metadata.tasks.Task.Status.IN_PROGRESS in project conductor by Netflix.

the class AbstractWorkflowServiceTest method testSubWorkflowRetry.

@Test
public void testSubWorkflowRetry() {
    String taskName = "junit_task_1";
    TaskDef taskDef = notFoundSafeGetTaskDef(taskName);
    int retryCount = notFoundSafeGetTaskDef(taskName).getRetryCount();
    taskDef.setRetryCount(0);
    metadataService.updateTaskDef(taskDef);
    // create a workflow with sub-workflow
    createSubWorkflow();
    WorkflowDef found = metadataService.getWorkflowDef(WF_WITH_SUB_WF, 1);
    WorkflowTask workflowTask = found.getTasks().stream().filter(t -> t.getType().equals(SUB_WORKFLOW.name())).findAny().orElse(null);
    // Set subworkflow task retry count to 1.
    TaskDef subWorkflowTaskDef = new TaskDef();
    subWorkflowTaskDef.setRetryCount(1);
    subWorkflowTaskDef.setName("test_subworkflow_task");
    subWorkflowTaskDef.setOwnerEmail("test@qbc.com");
    workflowTask.setTaskDefinition(subWorkflowTaskDef);
    metadataService.updateWorkflowDef(found);
    // start the workflow
    Map<String, Object> workflowInputParams = new HashMap<>();
    workflowInputParams.put("param1", "param 1");
    workflowInputParams.put("param3", "param 2");
    workflowInputParams.put("wfName", LINEAR_WORKFLOW_T1_T2);
    String workflowId = startOrLoadWorkflowExecution(WF_WITH_SUB_WF, 1, "test", workflowInputParams, null, null);
    assertNotNull(workflowId);
    Workflow workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    // poll and complete first task
    Task task = workflowExecutionService.poll("junit_task_5", "test");
    assertNotNull(task);
    task.setStatus(COMPLETED);
    workflowExecutionService.updateTask(task);
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    // Simulating SystemTaskWorkerCoordinator to execute async system tasks
    String subWorkflowTaskId = workflow.getTaskByRefName("a2").getTaskId();
    workflowExecutor.executeSystemTask(dummySubWorkflowSystemTask, subWorkflowTaskId, 1);
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    assertNotNull(workflow.getTasks());
    assertEquals(2, workflow.getTasks().size());
    task = workflow.getTasks().stream().filter(t -> t.getTaskType().equals(SUB_WORKFLOW.name())).findAny().orElse(null);
    assertNotNull(task);
    assertNotNull(task.getOutputData());
    assertNotNull("Output: " + task.getOutputData().toString() + ", status: " + task.getStatus(), task.getSubWorkflowId());
    String subWorkflowId = task.getSubWorkflowId();
    workflow = workflowExecutionService.getExecutionStatus(subWorkflowId, true);
    assertNotNull(workflow);
    assertNotNull(workflow.getTasks());
    assertEquals(workflowId, workflow.getParentWorkflowId());
    assertEquals(RUNNING, workflow.getStatus());
    // poll and fail the first task in sub-workflow
    task = workflowExecutionService.poll("junit_task_1", "test");
    task.setStatus(FAILED);
    workflowExecutionService.updateTask(task);
    Workflow subWorkflow = workflowExecutionService.getExecutionStatus(subWorkflowId, true);
    assertNotNull(subWorkflow);
    assertEquals(WorkflowStatus.FAILED, subWorkflow.getStatus());
    subWorkflowTaskId = subWorkflow.getParentWorkflowTaskId();
    workflowExecutor.executeSystemTask(subworkflow, subWorkflowTaskId, 1);
    // Ensure failed Subworkflow task is rescheduled.
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    assertEquals(RUNNING, workflow.getStatus());
    task = workflow.getTasks().stream().filter(t -> t.getTaskType().equals(SUB_WORKFLOW.name())).filter(t -> t.getStatus().equals(SCHEDULED)).findAny().orElse(null);
    assertNotNull(task);
    subWorkflowTaskId = task.getTaskId();
    workflowExecutor.executeSystemTask(subworkflow, task.getTaskId(), 1);
    // Get the latest workflow and task, and then acquire latest subWorkflowId
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    task = workflow.getTasks().stream().filter(t -> t.getTaskType().equals(SUB_WORKFLOW.name())).filter(t -> t.getStatus().equals(IN_PROGRESS)).findAny().orElse(null);
    assertNotNull(task);
    assertNotNull("Retried task in scheduled state shouldn't have a SubworkflowId yet", task.getSubWorkflowId());
    subWorkflowId = task.getSubWorkflowId();
    // poll and fail the first task in sub-workflow
    task = workflowExecutionService.poll("junit_task_1", "test");
    task.setStatus(FAILED);
    workflowExecutionService.updateTask(task);
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    assertEquals(WorkflowStatus.FAILED, workflow.getStatus());
    // Retry the failed sub workflow
    workflowExecutor.retry(subWorkflowId, false);
    task = workflowExecutionService.poll("junit_task_1", "test");
    task.setStatus(COMPLETED);
    workflowExecutionService.updateTask(task);
    subWorkflow = workflowExecutionService.getExecutionStatus(subWorkflowId, true);
    assertNotNull(subWorkflow);
    assertEquals(RUNNING, subWorkflow.getStatus());
    task = workflowExecutionService.poll("junit_task_2", "test");
    assertEquals(subWorkflowId, task.getWorkflowInstanceId());
    String uuid = UUID.randomUUID().toString();
    task.getOutputData().put("uuid", uuid);
    task.setStatus(COMPLETED);
    workflowExecutionService.updateTask(task);
    subWorkflow = workflowExecutionService.getExecutionStatus(subWorkflowId, true);
    assertNotNull(subWorkflow);
    assertEquals(WorkflowStatus.COMPLETED, subWorkflow.getStatus());
    assertNotNull(subWorkflow.getOutput());
    assertTrue(subWorkflow.getOutput().containsKey("o1"));
    assertTrue(subWorkflow.getOutput().containsKey("o2"));
    assertEquals("sub workflow input param1", subWorkflow.getOutput().get("o1"));
    assertEquals(uuid, subWorkflow.getOutput().get("o2"));
    // Simulating SystemTaskWorkerCoordinator
    workflowExecutor.executeSystemTask(subworkflow, subWorkflow.getParentWorkflowTaskId(), 1);
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    assertEquals(RUNNING, workflow.getStatus());
    task = workflowExecutionService.poll("junit_task_6", "test");
    assertNotNull(task);
    task.setStatus(COMPLETED);
    workflowExecutionService.updateTask(task);
    workflow = workflowExecutionService.getExecutionStatus(workflowId, true);
    assertNotNull(workflow);
    assertEquals(WorkflowStatus.COMPLETED, workflow.getStatus());
    // reset retry count
    taskDef = notFoundSafeGetTaskDef(taskName);
    taskDef.setRetryCount(retryCount);
    metadataService.updateTaskDef(taskDef);
    workflowTask = found.getTasks().stream().filter(t -> t.getType().equals(SUB_WORKFLOW.name())).findAny().orElse(null);
    workflowTask.setTaskDefinition(null);
    metadataService.updateWorkflowDef(found);
}
Also used : TaskUtils(com.netflix.conductor.common.utils.TaskUtils) MethodSorters(org.junit.runners.MethodSorters) SubWorkflow(com.netflix.conductor.core.execution.tasks.SubWorkflow) Arrays(java.util.Arrays) TimeoutPolicy(com.netflix.conductor.common.metadata.tasks.TaskDef.TimeoutPolicy) TEMP_FILE_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.TEMP_FILE_PATH) LoggerFactory(org.slf4j.LoggerFactory) Task(com.netflix.conductor.common.metadata.tasks.Task) StringUtils(org.apache.commons.lang3.StringUtils) Future(java.util.concurrent.Future) COMPLETED_WITH_ERRORS(com.netflix.conductor.common.metadata.tasks.Task.Status.COMPLETED_WITH_ERRORS) RerunWorkflowRequest(com.netflix.conductor.common.metadata.workflow.RerunWorkflowRequest) Workflow(com.netflix.conductor.common.run.Workflow) IN_PROGRESS(com.netflix.conductor.common.metadata.tasks.Task.Status.IN_PROGRESS) Map(java.util.Map) After(org.junit.After) PollData(com.netflix.conductor.common.metadata.tasks.PollData) WorkflowExecutor(com.netflix.conductor.core.execution.WorkflowExecutor) TASK_OUTPUT_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.TASK_OUTPUT_PATH) Terminate(com.netflix.conductor.core.execution.tasks.Terminate) WorkflowRepairService(com.netflix.conductor.core.execution.WorkflowRepairService) TaskDef(com.netflix.conductor.common.metadata.tasks.TaskDef) WorkflowStatus(com.netflix.conductor.common.run.Workflow.WorkflowStatus) MetadataMapperService(com.netflix.conductor.core.metadata.MetadataMapperService) Predicate(java.util.function.Predicate) Set(java.util.Set) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) Executors(java.util.concurrent.Executors) SCHEDULED(com.netflix.conductor.common.metadata.tasks.Task.Status.SCHEDULED) QueueDAO(com.netflix.conductor.dao.QueueDAO) INPUT_PAYLOAD_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.INPUT_PAYLOAD_PATH) List(java.util.List) DynamicForkJoinTaskList(com.netflix.conductor.common.metadata.workflow.DynamicForkJoinTaskList) Assert.assertFalse(org.junit.Assert.assertFalse) TIMED_OUT(com.netflix.conductor.common.metadata.tasks.Task.Status.TIMED_OUT) COMPLETED(com.netflix.conductor.common.metadata.tasks.Task.Status.COMPLETED) ExecutionService(com.netflix.conductor.service.ExecutionService) FixMethodOrder(org.junit.FixMethodOrder) JsonMapperProvider(com.netflix.conductor.common.utils.JsonMapperProvider) MetadataService(com.netflix.conductor.service.MetadataService) WorkflowContext(com.netflix.conductor.core.WorkflowContext) BeforeClass(org.junit.BeforeClass) SubWorkflowParams(com.netflix.conductor.common.metadata.workflow.SubWorkflowParams) Status(com.netflix.conductor.common.metadata.tasks.Task.Status) HashMap(java.util.HashMap) TaskResult(com.netflix.conductor.common.metadata.tasks.TaskResult) Inject(javax.inject.Inject) SUB_WORKFLOW(com.netflix.conductor.common.metadata.workflow.TaskType.SUB_WORKFLOW) LinkedList(java.util.LinkedList) ExpectedException(org.junit.rules.ExpectedException) RUNNING(com.netflix.conductor.common.run.Workflow.WorkflowStatus.RUNNING) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) TERMINATED(com.netflix.conductor.common.run.Workflow.WorkflowStatus.TERMINATED) INITIAL_WORKFLOW_INPUT_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.INITIAL_WORKFLOW_INPUT_PATH) ApplicationException(com.netflix.conductor.core.execution.ApplicationException) Uninterruptibles(com.google.common.util.concurrent.Uninterruptibles) Logger(org.slf4j.Logger) WorkflowSweeper(com.netflix.conductor.core.execution.WorkflowSweeper) Assert.assertNotNull(org.junit.Assert.assertNotNull) UserTask(com.netflix.conductor.tests.utils.UserTask) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Assert.assertTrue(org.junit.Assert.assertTrue) WorkflowDef(com.netflix.conductor.common.metadata.workflow.WorkflowDef) FileOutputStream(java.io.FileOutputStream) Test(org.junit.Test) FAILED(com.netflix.conductor.common.metadata.tasks.Task.Status.FAILED) WORKFLOW_OUTPUT_PATH(com.netflix.conductor.tests.utils.MockExternalPayloadStorage.WORKFLOW_OUTPUT_PATH) TimeUnit(java.util.concurrent.TimeUnit) DECISION(com.netflix.conductor.common.metadata.workflow.TaskType.DECISION) Assert.assertNull(org.junit.Assert.assertNull) Rule(org.junit.Rule) Ignore(org.junit.Ignore) RetryLogic(com.netflix.conductor.common.metadata.tasks.TaskDef.RetryLogic) TaskType(com.netflix.conductor.common.metadata.workflow.TaskType) Collections(java.util.Collections) Assert.assertEquals(org.junit.Assert.assertEquals) Task(com.netflix.conductor.common.metadata.tasks.Task) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) UserTask(com.netflix.conductor.tests.utils.UserTask) WorkflowDef(com.netflix.conductor.common.metadata.workflow.WorkflowDef) HashMap(java.util.HashMap) TaskDef(com.netflix.conductor.common.metadata.tasks.TaskDef) SubWorkflow(com.netflix.conductor.core.execution.tasks.SubWorkflow) Workflow(com.netflix.conductor.common.run.Workflow) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) Test(org.junit.Test)

Example 3 with IN_PROGRESS

use of com.netflix.conductor.common.metadata.tasks.Task.Status.IN_PROGRESS in project conductor by Netflix.

the class WorkflowExecutor method retry.

/**
 * Gets the last instance of each failed task and reschedule each
 * Gets all cancelled tasks and schedule all of them except JOIN (join should change status to INPROGRESS)
 * Switch workflow back to RUNNING status and call decider.
 *
 * @param workflowId the id of the workflow to be retried
 */
public void retry(String workflowId, boolean resumeSubworkflowTasks) {
    Workflow workflow = executionDAOFacade.getWorkflowById(workflowId, true);
    if (!workflow.getStatus().isTerminal()) {
        throw new ApplicationException(CONFLICT, "Workflow is still running.  status=" + workflow.getStatus());
    }
    if (workflow.getTasks().isEmpty()) {
        throw new ApplicationException(CONFLICT, "Workflow has not started yet");
    }
    if (resumeSubworkflowTasks) {
        Optional<Task> lTask = workflow.getTasks().stream().filter(this::findLastFailedOrTimeOutTask).findFirst();
        if (lTask.isPresent()) {
            workflow = findLastFailedSubWorkflow(lTask.get(), workflow);
        }
    }
    // Get all FAILED or CANCELED tasks that are not COMPLETED (or reach other terminal states) on further executions.
    // // Eg: for Seq of tasks task1.CANCELED, task1.COMPLETED, task1 shouldn't be retried.
    // Throw an exception if there are no FAILED tasks.
    // Handle JOIN task CANCELED status as special case.
    Map<String, Task> retriableMap = new HashMap<>();
    for (Task task : workflow.getTasks()) {
        switch(task.getStatus()) {
            case FAILED:
            case FAILED_WITH_TERMINAL_ERROR:
            case TIMED_OUT:
                retriableMap.put(task.getReferenceTaskName(), task);
                break;
            case CANCELED:
                if (task.getTaskType().equalsIgnoreCase(TaskType.JOIN.toString()) || task.getTaskType().equalsIgnoreCase(TaskType.DO_WHILE.toString())) {
                    task.setStatus(IN_PROGRESS);
                // Task doesn't have to be updated yet. Will be updated along with other Workflow tasks downstream.
                } else {
                    retriableMap.put(task.getReferenceTaskName(), task);
                }
                break;
            default:
                retriableMap.remove(task.getReferenceTaskName());
                break;
        }
    }
    if (retriableMap.values().size() == 0) {
        throw new ApplicationException(CONFLICT, "There are no retriable tasks! Use restart if you want to attempt entire workflow execution again.");
    }
    // Update Workflow with new status.
    // This should load Workflow from archive, if archived.
    workflow.setStatus(WorkflowStatus.RUNNING);
    workflow.setLastRetriedTime(System.currentTimeMillis());
    // Add to decider queue
    queueDAO.push(DECIDER_QUEUE, workflow.getWorkflowId(), workflow.getPriority(), config.getSweepFrequency());
    executionDAOFacade.updateWorkflow(workflow);
    // taskToBeRescheduled would set task `retried` to true, and hence it's important to updateTasks after obtaining task copy from taskToBeRescheduled.
    final Workflow finalWorkflow = workflow;
    List<Task> retriableTasks = retriableMap.values().stream().sorted(Comparator.comparingInt(Task::getSeq)).map(task -> taskToBeRescheduled(finalWorkflow, task)).collect(Collectors.toList());
    dedupAndAddTasks(workflow, retriableTasks);
    // Note: updateTasks before updateWorkflow might fail when Workflow is archived and doesn't exist in primary store.
    executionDAOFacade.updateTasks(workflow.getTasks());
    scheduleTask(workflow, retriableTasks);
    decide(workflowId);
    if (resumeSubworkflowTasks) {
        updateParentWorkflowRecursively(workflow);
    } else if (StringUtils.isNotEmpty(workflow.getParentWorkflowId())) {
        updateParentWorkflow(workflow);
        decide(workflow.getParentWorkflowId());
    }
}
Also used : TaskUtils(com.netflix.conductor.common.utils.TaskUtils) SubWorkflow(com.netflix.conductor.core.execution.tasks.SubWorkflow) ExecutionLockService(com.netflix.conductor.service.ExecutionLockService) Arrays(java.util.Arrays) INVALID_INPUT(com.netflix.conductor.core.execution.ApplicationException.Code.INVALID_INPUT) NOT_FOUND(com.netflix.conductor.core.execution.ApplicationException.Code.NOT_FOUND) QueueUtils(com.netflix.conductor.core.utils.QueueUtils) LoggerFactory(org.slf4j.LoggerFactory) MetadataDAO(com.netflix.conductor.dao.MetadataDAO) CANCELED(com.netflix.conductor.common.metadata.tasks.Task.Status.CANCELED) Task(com.netflix.conductor.common.metadata.tasks.Task) ExecutionDAOFacade(com.netflix.conductor.core.orchestration.ExecutionDAOFacade) StringUtils(org.apache.commons.lang3.StringUtils) WorkflowSystemTask(com.netflix.conductor.core.execution.tasks.WorkflowSystemTask) RerunWorkflowRequest(com.netflix.conductor.common.metadata.workflow.RerunWorkflowRequest) Workflow(com.netflix.conductor.common.run.Workflow) IN_PROGRESS(com.netflix.conductor.common.metadata.tasks.Task.Status.IN_PROGRESS) Map(java.util.Map) PollData(com.netflix.conductor.common.metadata.tasks.PollData) SKIPPED(com.netflix.conductor.common.metadata.tasks.Task.Status.SKIPPED) Terminate(com.netflix.conductor.core.execution.tasks.Terminate) Code(com.netflix.conductor.core.execution.ApplicationException.Code) TaskDef(com.netflix.conductor.common.metadata.tasks.TaskDef) Status.valueOf(com.netflix.conductor.common.metadata.tasks.Task.Status.valueOf) Trace(com.netflix.conductor.annotations.Trace) WorkflowStatus(com.netflix.conductor.common.run.Workflow.WorkflowStatus) MetadataMapperService(com.netflix.conductor.core.metadata.MetadataMapperService) Predicate(java.util.function.Predicate) Collectors(java.util.stream.Collectors) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) SCHEDULED(com.netflix.conductor.common.metadata.tasks.Task.Status.SCHEDULED) Objects(java.util.Objects) QueueDAO(com.netflix.conductor.dao.QueueDAO) List(java.util.List) TIMED_OUT(com.netflix.conductor.common.metadata.tasks.Task.Status.TIMED_OUT) Optional(java.util.Optional) Status(com.netflix.conductor.common.metadata.tasks.TaskResult.Status) Configuration(com.netflix.conductor.core.config.Configuration) CONFLICT(com.netflix.conductor.core.execution.ApplicationException.Code.CONFLICT) WorkflowContext(com.netflix.conductor.core.WorkflowContext) IDGenerator(com.netflix.conductor.core.utils.IDGenerator) HashMap(java.util.HashMap) TaskResult(com.netflix.conductor.common.metadata.tasks.TaskResult) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Inject(javax.inject.Inject) SUB_WORKFLOW(com.netflix.conductor.common.metadata.workflow.TaskType.SUB_WORKFLOW) SkipTaskRequest(com.netflix.conductor.common.metadata.workflow.SkipTaskRequest) FAILED_WITH_TERMINAL_ERROR(com.netflix.conductor.common.metadata.tasks.Task.Status.FAILED_WITH_TERMINAL_ERROR) Logger(org.slf4j.Logger) RetryUtil(com.netflix.conductor.common.utils.RetryUtil) WorkflowDef(com.netflix.conductor.common.metadata.workflow.WorkflowDef) FAILED(com.netflix.conductor.common.metadata.tasks.Task.Status.FAILED) Monitors(com.netflix.conductor.metrics.Monitors) TERMINATE(com.netflix.conductor.common.metadata.workflow.TaskType.TERMINATE) Preconditions(com.google.common.base.Preconditions) TaskType(com.netflix.conductor.common.metadata.workflow.TaskType) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Comparator(java.util.Comparator) Collections(java.util.Collections) Task(com.netflix.conductor.common.metadata.tasks.Task) WorkflowSystemTask(com.netflix.conductor.core.execution.tasks.WorkflowSystemTask) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) HashMap(java.util.HashMap) SubWorkflow(com.netflix.conductor.core.execution.tasks.SubWorkflow) Workflow(com.netflix.conductor.common.run.Workflow)

Aggregations

PollData (com.netflix.conductor.common.metadata.tasks.PollData)3 Task (com.netflix.conductor.common.metadata.tasks.Task)3 FAILED (com.netflix.conductor.common.metadata.tasks.Task.Status.FAILED)3 IN_PROGRESS (com.netflix.conductor.common.metadata.tasks.Task.Status.IN_PROGRESS)3 SCHEDULED (com.netflix.conductor.common.metadata.tasks.Task.Status.SCHEDULED)3 TIMED_OUT (com.netflix.conductor.common.metadata.tasks.Task.Status.TIMED_OUT)3 TaskDef (com.netflix.conductor.common.metadata.tasks.TaskDef)3 TaskResult (com.netflix.conductor.common.metadata.tasks.TaskResult)3 RerunWorkflowRequest (com.netflix.conductor.common.metadata.workflow.RerunWorkflowRequest)3 TaskType (com.netflix.conductor.common.metadata.workflow.TaskType)3 SUB_WORKFLOW (com.netflix.conductor.common.metadata.workflow.TaskType.SUB_WORKFLOW)3 WorkflowDef (com.netflix.conductor.common.metadata.workflow.WorkflowDef)3 WorkflowTask (com.netflix.conductor.common.metadata.workflow.WorkflowTask)3 Workflow (com.netflix.conductor.common.run.Workflow)3 WorkflowStatus (com.netflix.conductor.common.run.Workflow.WorkflowStatus)3 TaskUtils (com.netflix.conductor.common.utils.TaskUtils)3 WorkflowContext (com.netflix.conductor.core.WorkflowContext)3 SubWorkflow (com.netflix.conductor.core.execution.tasks.SubWorkflow)3 Terminate (com.netflix.conductor.core.execution.tasks.Terminate)3 MetadataMapperService (com.netflix.conductor.core.metadata.MetadataMapperService)3