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());
}
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);
}
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());
}
}
Aggregations