use of com.netflix.conductor.core.execution.tasks.WorkflowSystemTask in project conductor by Netflix.
the class TestWorkflowRepairService method verifyAndRepairSystemTask.
@Test
public void verifyAndRepairSystemTask() {
Task task = new Task();
task.setTaskType("TEST_SYS_TASK");
task.setStatus(Task.Status.SCHEDULED);
task.setTaskId("abcd");
task.setCallbackAfterSeconds(60);
// Create a Custom system task to init WorkflowSystemTask registry.
WorkflowSystemTask workflowSystemTask = new WorkflowSystemTask("TEST_SYS_TASK") {
@Override
public boolean isAsync() {
return true;
}
@Override
public boolean isAsyncComplete(Task task) {
return false;
}
@Override
public void start(Workflow workflow, Task task, WorkflowExecutor executor) {
super.start(workflow, task, executor);
}
};
when(queueDAO.containsMessage(anyString(), anyString())).thenReturn(false);
assertTrue(workflowRepairService.verifyAndRepairTask(task));
// Verify that a new queue message is pushed for tasks that fails queue contains check.
verify(queueDAO, times(1)).push(anyString(), anyString(), anyLong());
// Verify a system task in IN_PROGRESS state can be recovered.
Mockito.reset(queueDAO);
task.setStatus(Task.Status.IN_PROGRESS);
assertTrue(workflowRepairService.verifyAndRepairTask(task));
// Verify that a new queue message is pushed for async System task in IN_PROGRESS state that fails queue contains check.
verify(queueDAO, times(1)).push(anyString(), anyString(), anyLong());
}
use of com.netflix.conductor.core.execution.tasks.WorkflowSystemTask in project conductor by Netflix.
the class TestWorkflowRepairService method assertAsyncCompleteSystemTasksAreNotCheckedAgainstQueue.
@Test
public void assertAsyncCompleteSystemTasksAreNotCheckedAgainstQueue() {
Task task = new Task();
task.setTaskType("SUB_WORKFLOW");
task.setStatus(Task.Status.IN_PROGRESS);
task.setTaskId("abcd");
task.setCallbackAfterSeconds(60);
WorkflowSystemTask workflowSystemTask = new SubWorkflow();
assertTrue(workflowSystemTask.isAsyncComplete(task));
assertFalse(workflowRepairService.verifyAndRepairTask(task));
// Verify that queue message is never pushed for async complete system tasks
verify(queueDAO, never()).containsMessage(anyString(), anyString());
verify(queueDAO, never()).push(anyString(), anyString(), anyLong());
}
use of com.netflix.conductor.core.execution.tasks.WorkflowSystemTask in project conductor by Netflix.
the class WorkflowExecutor method decide.
/**
* @param workflowId ID of the workflow to evaluate the state for
* @return true if the workflow has completed (success or failed), false otherwise.
* @throws ApplicationException If there was an error - caller should retry in this case.
*/
public boolean decide(String workflowId) {
if (!executionLockService.acquireLock(workflowId)) {
return false;
}
// If it is a new workflow, the tasks will be still empty even though include tasks is true
Workflow workflow = executionDAOFacade.getWorkflowById(workflowId, true);
// FIXME Backwards compatibility for legacy workflows already running.
// This code will be removed in a future version.
workflow = metadataMapperService.populateWorkflowWithDefinitions(workflow);
if (workflow.getStatus().isTerminal()) {
if (!workflow.getStatus().isSuccessful()) {
cancelNonTerminalTasks(workflow);
}
return true;
}
try {
DeciderService.DeciderOutcome outcome = deciderService.decide(workflow);
if (outcome.isComplete) {
endExecution(workflow);
return true;
}
List<Task> tasksToBeScheduled = outcome.tasksToBeScheduled;
setTaskDomains(tasksToBeScheduled, workflow);
List<Task> tasksToBeUpdated = outcome.tasksToBeUpdated;
boolean stateChanged = false;
tasksToBeScheduled = dedupAndAddTasks(workflow, tasksToBeScheduled);
for (Task task : outcome.tasksToBeScheduled) {
if (isSystemTask.and(isNonTerminalTask).test(task)) {
WorkflowSystemTask workflowSystemTask = WorkflowSystemTask.get(task.getTaskType());
Workflow workflowInstance = deciderService.populateWorkflowAndTaskData(workflow);
if (!workflowSystemTask.isAsync() && workflowSystemTask.execute(workflowInstance, task, this)) {
deciderService.externalizeTaskData(task);
tasksToBeUpdated.add(task);
stateChanged = true;
}
}
}
if (!outcome.tasksToBeUpdated.isEmpty() || !tasksToBeScheduled.isEmpty()) {
executionDAOFacade.updateTasks(tasksToBeUpdated);
executionDAOFacade.updateWorkflow(workflow);
}
stateChanged = scheduleTask(workflow, tasksToBeScheduled) || stateChanged;
if (stateChanged) {
decide(workflowId);
}
} catch (TerminateWorkflowException twe) {
LOGGER.info("Execution terminated of workflow: {}", workflowId, twe);
terminate(workflow, twe);
return true;
} catch (RuntimeException e) {
LOGGER.error("Error deciding workflow: {}", workflowId, e);
throw e;
} finally {
executionLockService.releaseLock(workflowId);
}
return false;
}
use of com.netflix.conductor.core.execution.tasks.WorkflowSystemTask in project conductor by Netflix.
the class WorkflowExecutor method executeSubworkflowTaskAndSyncData.
private void executeSubworkflowTaskAndSyncData(Workflow subWorkflow, Task subWorkflowTask) {
WorkflowSystemTask subWorkflowSystemTask = WorkflowSystemTask.get(SubWorkflow.NAME);
subWorkflowSystemTask.execute(subWorkflow, subWorkflowTask, this);
// Keep Subworkflow task's data consistent with Subworkflow's.
if (subWorkflowTask.getStatus().isTerminal() && subWorkflowTask.getExternalOutputPayloadStoragePath() != null && !subWorkflowTask.getOutputData().isEmpty()) {
Map<String, Object> parentWorkflowTaskOutputData = subWorkflowTask.getOutputData();
deciderService.populateTaskData(subWorkflowTask);
subWorkflowTask.getOutputData().putAll(parentWorkflowTaskOutputData);
deciderService.externalizeTaskData(subWorkflowTask);
}
}
use of com.netflix.conductor.core.execution.tasks.WorkflowSystemTask in project conductor by Netflix.
the class TestWorkflowExecutor method testScheduleTask.
@Test
public void testScheduleTask() {
AtomicBoolean httpTaskExecuted = new AtomicBoolean(false);
AtomicBoolean http2TaskExecuted = new AtomicBoolean(false);
new Wait();
new WorkflowSystemTask("HTTP") {
@Override
public boolean isAsync() {
return true;
}
@Override
public void start(Workflow workflow, Task task, WorkflowExecutor executor) {
httpTaskExecuted.set(true);
task.setStatus(Status.COMPLETED);
super.start(workflow, task, executor);
}
};
new WorkflowSystemTask("HTTP2") {
@Override
public void start(Workflow workflow, Task task, WorkflowExecutor executor) {
http2TaskExecuted.set(true);
task.setStatus(Status.COMPLETED);
super.start(workflow, task, executor);
}
};
Workflow workflow = new Workflow();
workflow.setWorkflowId("1");
List<Task> tasks = new LinkedList<>();
WorkflowTask taskToSchedule = new WorkflowTask();
taskToSchedule.setWorkflowTaskType(TaskType.USER_DEFINED);
taskToSchedule.setType("HTTP");
WorkflowTask taskToSchedule2 = new WorkflowTask();
taskToSchedule2.setWorkflowTaskType(TaskType.USER_DEFINED);
taskToSchedule2.setType("HTTP2");
WorkflowTask wait = new WorkflowTask();
wait.setWorkflowTaskType(TaskType.WAIT);
wait.setType("WAIT");
wait.setTaskReferenceName("wait");
Task task1 = new Task();
task1.setTaskType(taskToSchedule.getType());
task1.setTaskDefName(taskToSchedule.getName());
task1.setReferenceTaskName(taskToSchedule.getTaskReferenceName());
task1.setWorkflowInstanceId(workflow.getWorkflowId());
task1.setCorrelationId(workflow.getCorrelationId());
task1.setScheduledTime(System.currentTimeMillis());
task1.setTaskId(IDGenerator.generate());
task1.setInputData(new HashMap<>());
task1.setStatus(Status.SCHEDULED);
task1.setRetryCount(0);
task1.setCallbackAfterSeconds(taskToSchedule.getStartDelay());
task1.setWorkflowTask(taskToSchedule);
Task task2 = new Task();
task2.setTaskType(Wait.NAME);
task2.setTaskDefName(taskToSchedule.getName());
task2.setReferenceTaskName(taskToSchedule.getTaskReferenceName());
task2.setWorkflowInstanceId(workflow.getWorkflowId());
task2.setCorrelationId(workflow.getCorrelationId());
task2.setScheduledTime(System.currentTimeMillis());
task2.setInputData(new HashMap<>());
task2.setTaskId(IDGenerator.generate());
task2.setStatus(Status.IN_PROGRESS);
task2.setWorkflowTask(taskToSchedule);
Task task3 = new Task();
task3.setTaskType(taskToSchedule2.getType());
task3.setTaskDefName(taskToSchedule.getName());
task3.setReferenceTaskName(taskToSchedule.getTaskReferenceName());
task3.setWorkflowInstanceId(workflow.getWorkflowId());
task3.setCorrelationId(workflow.getCorrelationId());
task3.setScheduledTime(System.currentTimeMillis());
task3.setTaskId(IDGenerator.generate());
task3.setInputData(new HashMap<>());
task3.setStatus(Status.SCHEDULED);
task3.setRetryCount(0);
task3.setCallbackAfterSeconds(taskToSchedule.getStartDelay());
task3.setWorkflowTask(taskToSchedule);
tasks.add(task1);
tasks.add(task2);
tasks.add(task3);
when(executionDAOFacade.createTasks(tasks)).thenReturn(tasks);
AtomicInteger startedTaskCount = new AtomicInteger(0);
doAnswer(invocation -> {
startedTaskCount.incrementAndGet();
return null;
}).when(executionDAOFacade).updateTask(any());
AtomicInteger queuedTaskCount = new AtomicInteger(0);
final Answer answer = invocation -> {
String queueName = invocation.getArgument(0, String.class);
System.out.println(queueName);
queuedTaskCount.incrementAndGet();
return null;
};
doAnswer(answer).when(queueDAO).push(any(), any(), anyLong());
doAnswer(answer).when(queueDAO).push(any(), any(), anyInt(), anyLong());
boolean stateChanged = workflowExecutor.scheduleTask(workflow, tasks);
assertEquals(2, startedTaskCount.get());
assertEquals(1, queuedTaskCount.get());
assertTrue(stateChanged);
assertFalse(httpTaskExecuted.get());
assertTrue(http2TaskExecuted.get());
}
Aggregations