Search in sources :

Example 81 with Workflow

use of com.netflix.conductor.common.run.Workflow in project conductor by Netflix.

the class DeciderService method startWorkflow.

private List<Task> startWorkflow(Workflow workflow) throws TerminateWorkflowException {
    final WorkflowDef workflowDef = workflow.getWorkflowDefinition();
    LOGGER.debug("Starting workflow: {}", workflow);
    // The tasks will be empty in case of new workflow
    List<Task> tasks = workflow.getTasks();
    // Check if the workflow is a re-run case or if it is a new workflow execution
    if (workflow.getReRunFromWorkflowId() == null || tasks.isEmpty()) {
        if (workflowDef.getTasks().isEmpty()) {
            throw new TerminateWorkflowException("No tasks found to be executed", WorkflowStatus.COMPLETED);
        }
        // Nothing is running yet - so schedule the first task
        WorkflowTask taskToSchedule = workflowDef.getTasks().get(0);
        // Loop until a non-skipped task is found
        while (isTaskSkipped(taskToSchedule, workflow)) {
            taskToSchedule = workflowDef.getNextTask(taskToSchedule.getTaskReferenceName());
        }
        // In case of a new workflow, the first non-skippable task will be scheduled
        return getTasksToBeScheduled(workflow, taskToSchedule, 0);
    }
    // Get the first task to schedule
    Task rerunFromTask = tasks.stream().findFirst().map(task -> {
        task.setStatus(SCHEDULED);
        task.setRetried(true);
        task.setRetryCount(0);
        return task;
    }).orElseThrow(() -> {
        String reason = String.format("The workflow %s is marked for re-run from %s but could not find the starting task", workflow.getWorkflowId(), workflow.getReRunFromWorkflowId());
        return new TerminateWorkflowException(reason);
    });
    return Collections.singletonList(rerunFromTask);
}
Also used : TaskUtils(com.netflix.conductor.common.utils.TaskUtils) TaskMapper(com.netflix.conductor.core.execution.mapper.TaskMapper) IDGenerator(com.netflix.conductor.core.utils.IDGenerator) Status(com.netflix.conductor.common.metadata.tasks.Task.Status) LoggerFactory(org.slf4j.LoggerFactory) TaskMapperContext(com.netflix.conductor.core.execution.mapper.TaskMapperContext) HashMap(java.util.HashMap) MetadataDAO(com.netflix.conductor.dao.MetadataDAO) Task(com.netflix.conductor.common.metadata.tasks.Task) StringUtils(org.apache.commons.lang3.StringUtils) LinkedHashMap(java.util.LinkedHashMap) Inject(javax.inject.Inject) SUB_WORKFLOW(com.netflix.conductor.common.metadata.workflow.TaskType.SUB_WORKFLOW) COMPLETED_WITH_ERRORS(com.netflix.conductor.common.metadata.tasks.Task.Status.COMPLETED_WITH_ERRORS) ExternalPayloadStorageUtils(com.netflix.conductor.core.utils.ExternalPayloadStorageUtils) Workflow(com.netflix.conductor.common.run.Workflow) IN_PROGRESS(com.netflix.conductor.common.metadata.tasks.Task.Status.IN_PROGRESS) Map(java.util.Map) SKIPPED(com.netflix.conductor.common.metadata.tasks.Task.Status.SKIPPED) Operation(com.netflix.conductor.common.utils.ExternalPayloadStorage.Operation) Named(javax.inject.Named) LinkedList(java.util.LinkedList) Nullable(javax.annotation.Nullable) TaskDef(com.netflix.conductor.common.metadata.tasks.TaskDef) Logger(org.slf4j.Logger) WorkflowStatus(com.netflix.conductor.common.run.Workflow.WorkflowStatus) Predicate(java.util.function.Predicate) WorkflowDef(com.netflix.conductor.common.metadata.workflow.WorkflowDef) Set(java.util.Set) Collectors(java.util.stream.Collectors) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) SCHEDULED(com.netflix.conductor.common.metadata.tasks.Task.Status.SCHEDULED) Monitors(com.netflix.conductor.metrics.Monitors) TERMINATE(com.netflix.conductor.common.metadata.workflow.TaskType.TERMINATE) List(java.util.List) TIMED_OUT(com.netflix.conductor.common.metadata.tasks.Task.Status.TIMED_OUT) Optional(java.util.Optional) TaskType(com.netflix.conductor.common.metadata.workflow.TaskType) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Configuration(com.netflix.conductor.core.config.Configuration) PayloadType(com.netflix.conductor.common.utils.ExternalPayloadStorage.PayloadType) Collections(java.util.Collections) Task(com.netflix.conductor.common.metadata.tasks.Task) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) WorkflowDef(com.netflix.conductor.common.metadata.workflow.WorkflowDef) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask)

Example 82 with Workflow

use of com.netflix.conductor.common.run.Workflow in project conductor by Netflix.

the class SimpleActionProcessor method completeTask.

private Map<String, Object> completeTask(Action action, Object payload, TaskDetails taskDetails, Status status, String event, String messageId) {
    Map<String, Object> input = new HashMap<>();
    input.put("workflowId", taskDetails.getWorkflowId());
    input.put("taskId", taskDetails.getTaskId());
    input.put("taskRefName", taskDetails.getTaskRefName());
    input.putAll(taskDetails.getOutput());
    Map<String, Object> replaced = parametersUtils.replace(input, payload);
    String workflowId = (String) replaced.get("workflowId");
    String taskId = (String) replaced.get("taskId");
    String taskRefName = (String) replaced.get("taskRefName");
    Task task = null;
    if (StringUtils.isNotEmpty(taskId)) {
        task = executor.getTask(taskId);
    } else if (StringUtils.isNotEmpty(workflowId) && StringUtils.isNotEmpty(taskRefName)) {
        Workflow workflow = executor.getWorkflow(workflowId, true);
        if (workflow == null) {
            replaced.put("error", "No workflow found with ID: " + workflowId);
            return replaced;
        }
        task = workflow.getTaskByRefName(taskRefName);
    }
    if (task == null) {
        replaced.put("error", "No task found with taskId: " + taskId + ", reference name: " + taskRefName + ", workflowId: " + workflowId);
        return replaced;
    }
    task.setStatus(status);
    task.setOutputData(replaced);
    task.setOutputMessage(taskDetails.getOutputMessage());
    task.getOutputData().put("conductor.event.messageId", messageId);
    task.getOutputData().put("conductor.event.name", event);
    try {
        executor.updateTask(new TaskResult(task));
        logger.debug("Updated task: {} in workflow:{} with status: {} for event: {} for message:{}", taskId, workflowId, status, event, messageId);
    } catch (RuntimeException e) {
        Monitors.recordEventActionError(action.getAction().name(), task.getTaskType(), event);
        logger.error("Error updating task: {} in workflow: {} in action: {} for event: {} for message: {}", taskDetails.getTaskRefName(), taskDetails.getWorkflowId(), action.getAction(), event, messageId, e);
        replaced.put("error", e.getMessage());
        throw e;
    }
    return replaced;
}
Also used : Task(com.netflix.conductor.common.metadata.tasks.Task) HashMap(java.util.HashMap) StartWorkflow(com.netflix.conductor.common.metadata.events.EventHandler.StartWorkflow) Workflow(com.netflix.conductor.common.run.Workflow) TaskResult(com.netflix.conductor.common.metadata.tasks.TaskResult)

Example 83 with Workflow

use of com.netflix.conductor.common.run.Workflow in project conductor by Netflix.

the class WorkflowRepairService method verifyAndRepairWorkflow.

/**
 * Verify and repair if the workflowId exists in deciderQueue, and then if each scheduled task has relevant message
 * in the queue.
 * @param workflowId
 * @param includeTasks
 * @return
 */
public boolean verifyAndRepairWorkflow(String workflowId, boolean includeTasks) {
    Workflow workflow = executionDAO.getWorkflow(workflowId, includeTasks);
    AtomicBoolean repaired = new AtomicBoolean(false);
    repaired.set(verifyAndRepairDeciderQueue(workflow));
    if (includeTasks) {
        workflow.getTasks().forEach(task -> {
            repaired.set(verifyAndRepairTask(task));
        });
    }
    return repaired.get();
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Workflow(com.netflix.conductor.common.run.Workflow)

Example 84 with Workflow

use of com.netflix.conductor.common.run.Workflow in project conductor by Netflix.

the class DecisionTaskMapper method getMappedTasks.

/**
 * This method gets the list of tasks that need to scheduled when the task to scheduled is of type {@link TaskType#DECISION}.
 *
 * @param taskMapperContext: A wrapper class containing the {@link WorkflowTask}, {@link WorkflowDef}, {@link Workflow} and a string representation of the TaskId
 * @return List of tasks in the following order:
 * <ul>
 * <li>
 * {@link SystemTaskType#DECISION} with {@link Task.Status#IN_PROGRESS}
 * </li>
 * <li>
 * List of task based on the evaluation of {@link WorkflowTask#getCaseExpression()} are scheduled.
 * </li>
 * <li>
 * In case of no matching result after the evaluation of the {@link WorkflowTask#getCaseExpression()}, the {@link WorkflowTask#getDefaultCase()}
 * Tasks are scheduled.
 * </li>
 * </ul>
 */
@Override
public List<Task> getMappedTasks(TaskMapperContext taskMapperContext) {
    logger.debug("TaskMapperContext {} in DecisionTaskMapper", taskMapperContext);
    List<Task> tasksToBeScheduled = new LinkedList<>();
    WorkflowTask taskToSchedule = taskMapperContext.getTaskToSchedule();
    Workflow workflowInstance = taskMapperContext.getWorkflowInstance();
    Map<String, Object> taskInput = taskMapperContext.getTaskInput();
    int retryCount = taskMapperContext.getRetryCount();
    String taskId = taskMapperContext.getTaskId();
    // get the expression to be evaluated
    String caseValue = getEvaluatedCaseValue(taskToSchedule, taskInput);
    // QQ why is the case value and the caseValue passed and caseOutput passes as the same ??
    Task decisionTask = new Task();
    decisionTask.setTaskType(SystemTaskType.DECISION.name());
    decisionTask.setTaskDefName(SystemTaskType.DECISION.name());
    decisionTask.setReferenceTaskName(taskToSchedule.getTaskReferenceName());
    decisionTask.setWorkflowInstanceId(workflowInstance.getWorkflowId());
    decisionTask.setWorkflowType(workflowInstance.getWorkflowName());
    decisionTask.setCorrelationId(workflowInstance.getCorrelationId());
    decisionTask.setScheduledTime(System.currentTimeMillis());
    decisionTask.getInputData().put("case", caseValue);
    decisionTask.getOutputData().put("caseOutput", Collections.singletonList(caseValue));
    decisionTask.setTaskId(taskId);
    decisionTask.setStartTime(System.currentTimeMillis());
    decisionTask.setStatus(Task.Status.IN_PROGRESS);
    decisionTask.setWorkflowTask(taskToSchedule);
    decisionTask.setWorkflowPriority(workflowInstance.getPriority());
    tasksToBeScheduled.add(decisionTask);
    // get the list of tasks based on the decision
    List<WorkflowTask> selectedTasks = taskToSchedule.getDecisionCases().get(caseValue);
    // if the tasks returned are empty based on evaluated case value, then get the default case if there is one
    if (selectedTasks == null || selectedTasks.isEmpty()) {
        selectedTasks = taskToSchedule.getDefaultCase();
    }
    // scheduled by using the decider service
    if (selectedTasks != null && !selectedTasks.isEmpty()) {
        // Schedule the first task to be executed...
        WorkflowTask selectedTask = selectedTasks.get(0);
        // TODO break out this recursive call using function composition of what needs to be done and then walk back the condition tree
        List<Task> caseTasks = taskMapperContext.getDeciderService().getTasksToBeScheduled(workflowInstance, selectedTask, retryCount, taskMapperContext.getRetryTaskId());
        tasksToBeScheduled.addAll(caseTasks);
        decisionTask.getInputData().put("hasChildren", "true");
    }
    return tasksToBeScheduled;
}
Also used : Task(com.netflix.conductor.common.metadata.tasks.Task) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) Workflow(com.netflix.conductor.common.run.Workflow) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) LinkedList(java.util.LinkedList)

Example 85 with Workflow

use of com.netflix.conductor.common.run.Workflow in project conductor by Netflix.

the class DoWhileTaskMapper method getMappedTasks.

/**
 * This method maps {@link TaskMapper} to map a {@link WorkflowTask} of type {@link TaskType#DO_WHILE} to a {@link Task} of type {@link SystemTaskType#DO_WHILE}
 * with a status of {@link Task.Status#IN_PROGRESS}
 *
 * @param taskMapperContext: A wrapper class containing the {@link WorkflowTask}, {@link WorkflowDef}, {@link Workflow} and a string representation of the TaskId
 * @return: A {@link Task} of type {@link SystemTaskType#DO_WHILE} in a List
 */
@Override
public List<Task> getMappedTasks(TaskMapperContext taskMapperContext) {
    logger.debug("TaskMapperContext {} in DoWhileTaskMapper", taskMapperContext);
    WorkflowTask taskToSchedule = taskMapperContext.getTaskToSchedule();
    Workflow workflowInstance = taskMapperContext.getWorkflowInstance();
    Task task = workflowInstance.getTaskByRefName(taskToSchedule.getTaskReferenceName());
    if (task != null && task.getStatus().isTerminal()) {
        // Since loopTask is already completed no need to schedule task again.
        return Collections.emptyList();
    }
    String taskId = taskMapperContext.getTaskId();
    List<Task> tasksToBeScheduled = new ArrayList<>();
    int retryCount = taskMapperContext.getRetryCount();
    TaskDef taskDefinition = Optional.ofNullable(taskMapperContext.getTaskDefinition()).orElseGet(() -> Optional.ofNullable(metadataDAO.getTaskDef(taskToSchedule.getName())).orElseGet(TaskDef::new));
    Task loopTask = new Task();
    loopTask.setTaskType(SystemTaskType.DO_WHILE.name());
    loopTask.setTaskDefName(taskToSchedule.getName());
    loopTask.setReferenceTaskName(taskToSchedule.getTaskReferenceName());
    loopTask.setWorkflowInstanceId(workflowInstance.getWorkflowId());
    loopTask.setCorrelationId(workflowInstance.getCorrelationId());
    loopTask.setWorkflowType(workflowInstance.getWorkflowName());
    loopTask.setScheduledTime(System.currentTimeMillis());
    loopTask.setTaskId(taskId);
    loopTask.setIteration(1);
    loopTask.setStatus(Task.Status.IN_PROGRESS);
    loopTask.setWorkflowTask(taskToSchedule);
    loopTask.setRateLimitPerFrequency(taskDefinition.getRateLimitPerFrequency());
    loopTask.setRateLimitFrequencyInSeconds(taskDefinition.getRateLimitFrequencyInSeconds());
    tasksToBeScheduled.add(loopTask);
    List<WorkflowTask> loopOverTasks = taskToSchedule.getLoopOver();
    List<Task> tasks2 = taskMapperContext.getDeciderService().getTasksToBeScheduled(workflowInstance, loopOverTasks.get(0), retryCount);
    tasks2.forEach(t -> {
        t.setReferenceTaskName(TaskUtils.appendIteration(t.getReferenceTaskName(), loopTask.getIteration()));
        t.setIteration(loopTask.getIteration());
    });
    tasksToBeScheduled.addAll(tasks2);
    return tasksToBeScheduled;
}
Also used : Task(com.netflix.conductor.common.metadata.tasks.Task) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) TaskDef(com.netflix.conductor.common.metadata.tasks.TaskDef) ArrayList(java.util.ArrayList) Workflow(com.netflix.conductor.common.run.Workflow) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask)

Aggregations

Workflow (com.netflix.conductor.common.run.Workflow)360 Test (org.junit.Test)259 Task (com.netflix.conductor.common.metadata.tasks.Task)246 WorkflowTask (com.netflix.conductor.common.metadata.workflow.WorkflowTask)206 HashMap (java.util.HashMap)154 WorkflowDef (com.netflix.conductor.common.metadata.workflow.WorkflowDef)149 SubWorkflow (com.netflix.conductor.core.execution.tasks.SubWorkflow)130 TaskDef (com.netflix.conductor.common.metadata.tasks.TaskDef)97 UserTask (com.netflix.conductor.tests.utils.UserTask)73 LinkedList (java.util.LinkedList)57 Map (java.util.Map)55 List (java.util.List)54 ApplicationException (com.netflix.conductor.core.execution.ApplicationException)52 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)50 Collections (java.util.Collections)36 Collectors (java.util.stream.Collectors)35 Logger (org.slf4j.Logger)35 LoggerFactory (org.slf4j.LoggerFactory)35 TaskResult (com.netflix.conductor.common.metadata.tasks.TaskResult)34 WorkflowSystemTask (com.netflix.conductor.core.execution.tasks.WorkflowSystemTask)34