Search in sources :

Example 1 with SKIPPED

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

the class DeciderService method decide.

private DeciderOutcome decide(final Workflow workflow, List<Task> preScheduledTasks) throws TerminateWorkflowException {
    DeciderOutcome outcome = new DeciderOutcome();
    if (workflow.getStatus().isTerminal()) {
        // you cannot evaluate a terminal workflow
        LOGGER.debug("Workflow {} is already finished. Reason: {}", workflow, workflow.getReasonForIncompletion());
        return outcome;
    }
    checkWorkflowTimeout(workflow);
    if (workflow.getStatus().equals(WorkflowStatus.PAUSED)) {
        LOGGER.debug("Workflow " + workflow.getWorkflowId() + " is paused");
        return outcome;
    }
    // Filter the list of tasks and include only tasks that are not retried, not executed
    // marked to be skipped and not part of System tasks that is DECISION, FORK, JOIN
    // This list will be empty for a new workflow being started
    List<Task> pendingTasks = workflow.getTasks().stream().filter(isNonPendingTask).collect(Collectors.toList());
    // Get all the tasks that have not completed their lifecycle yet
    // This list will be empty for a new workflow
    Set<String> executedTaskRefNames = workflow.getTasks().stream().filter(Task::isExecuted).map(Task::getReferenceTaskName).collect(Collectors.toSet());
    Map<String, Task> tasksToBeScheduled = new LinkedHashMap<>();
    preScheduledTasks.forEach(preScheduledTask -> {
        tasksToBeScheduled.put(preScheduledTask.getReferenceTaskName(), preScheduledTask);
    });
    // A new workflow does not enter this code branch
    for (Task pendingTask : pendingTasks) {
        if (SystemTaskType.is(pendingTask.getTaskType()) && !pendingTask.getStatus().isTerminal()) {
            tasksToBeScheduled.putIfAbsent(pendingTask.getReferenceTaskName(), pendingTask);
            executedTaskRefNames.remove(pendingTask.getReferenceTaskName());
        }
        Optional<TaskDef> taskDefinition = pendingTask.getTaskDefinition();
        if (!taskDefinition.isPresent()) {
            taskDefinition = Optional.ofNullable(workflow.getWorkflowDefinition().getTaskByRefName(pendingTask.getReferenceTaskName())).map(WorkflowTask::getTaskDefinition);
        }
        if (taskDefinition.isPresent()) {
            checkTaskTimeout(taskDefinition.get(), pendingTask);
            checkTaskPollTimeout(taskDefinition.get(), pendingTask);
            // If the task has not been updated for "responseTimeoutSeconds" then mark task as TIMED_OUT
            if (isResponseTimedOut(taskDefinition.get(), pendingTask)) {
                timeoutTask(taskDefinition.get(), pendingTask);
            }
        }
        if (!pendingTask.getStatus().isSuccessful()) {
            WorkflowTask workflowTask = pendingTask.getWorkflowTask();
            if (workflowTask == null) {
                workflowTask = workflow.getWorkflowDefinition().getTaskByRefName(pendingTask.getReferenceTaskName());
            }
            Optional<Task> retryTask = retry(taskDefinition.orElse(null), workflowTask, pendingTask, workflow);
            if (retryTask.isPresent()) {
                tasksToBeScheduled.put(retryTask.get().getReferenceTaskName(), retryTask.get());
                executedTaskRefNames.remove(retryTask.get().getReferenceTaskName());
                outcome.tasksToBeUpdated.add(pendingTask);
            } else {
                pendingTask.setStatus(COMPLETED_WITH_ERRORS);
            }
        }
        if (!pendingTask.isExecuted() && !pendingTask.isRetried() && pendingTask.getStatus().isTerminal()) {
            pendingTask.setExecuted(true);
            List<Task> nextTasks = getNextTask(workflow, pendingTask);
            if (pendingTask.isLoopOverTask() && !TaskType.DO_WHILE.name().equals(pendingTask.getTaskType()) && !nextTasks.isEmpty()) {
                nextTasks = filterNextLoopOverTasks(nextTasks, pendingTask, workflow);
            }
            nextTasks.forEach(nextTask -> tasksToBeScheduled.putIfAbsent(nextTask.getReferenceTaskName(), nextTask));
            outcome.tasksToBeUpdated.add(pendingTask);
            LOGGER.debug("Scheduling Tasks from {}, next = {} for workflowId: {}", pendingTask.getTaskDefName(), nextTasks.stream().map(Task::getTaskDefName).collect(Collectors.toList()), workflow.getWorkflowId());
        }
    }
    // All the tasks that need to scheduled are added to the outcome, in case of
    List<Task> unScheduledTasks = tasksToBeScheduled.values().stream().filter(task -> !executedTaskRefNames.contains(task.getReferenceTaskName())).collect(Collectors.toList());
    if (!unScheduledTasks.isEmpty()) {
        LOGGER.debug("Scheduling Tasks: {} for workflow: {}", unScheduledTasks.stream().map(Task::getTaskDefName).collect(Collectors.toList()), workflow.getWorkflowId());
        outcome.tasksToBeScheduled.addAll(unScheduledTasks);
    }
    if (containsSuccessfulTerminateTask.test(workflow) || (outcome.tasksToBeScheduled.isEmpty() && checkForWorkflowCompletion(workflow))) {
        LOGGER.debug("Marking workflow: {} as complete.", workflow);
        outcome.isComplete = true;
    }
    return outcome;
}
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) TaskDef(com.netflix.conductor.common.metadata.tasks.TaskDef) WorkflowTask(com.netflix.conductor.common.metadata.workflow.WorkflowTask) LinkedHashMap(java.util.LinkedHashMap)

Example 2 with SKIPPED

use of com.netflix.conductor.common.metadata.tasks.Task.Status.SKIPPED 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)

Aggregations

VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 Task (com.netflix.conductor.common.metadata.tasks.Task)2 Status (com.netflix.conductor.common.metadata.tasks.Task.Status)2 COMPLETED_WITH_ERRORS (com.netflix.conductor.common.metadata.tasks.Task.Status.COMPLETED_WITH_ERRORS)2 IN_PROGRESS (com.netflix.conductor.common.metadata.tasks.Task.Status.IN_PROGRESS)2 SCHEDULED (com.netflix.conductor.common.metadata.tasks.Task.Status.SCHEDULED)2 SKIPPED (com.netflix.conductor.common.metadata.tasks.Task.Status.SKIPPED)2 TIMED_OUT (com.netflix.conductor.common.metadata.tasks.Task.Status.TIMED_OUT)2 TaskDef (com.netflix.conductor.common.metadata.tasks.TaskDef)2 TaskType (com.netflix.conductor.common.metadata.workflow.TaskType)2 SUB_WORKFLOW (com.netflix.conductor.common.metadata.workflow.TaskType.SUB_WORKFLOW)2 TERMINATE (com.netflix.conductor.common.metadata.workflow.TaskType.TERMINATE)2 WorkflowDef (com.netflix.conductor.common.metadata.workflow.WorkflowDef)2 WorkflowTask (com.netflix.conductor.common.metadata.workflow.WorkflowTask)2 Workflow (com.netflix.conductor.common.run.Workflow)2 WorkflowStatus (com.netflix.conductor.common.run.Workflow.WorkflowStatus)2 Operation (com.netflix.conductor.common.utils.ExternalPayloadStorage.Operation)2 PayloadType (com.netflix.conductor.common.utils.ExternalPayloadStorage.PayloadType)2 TaskUtils (com.netflix.conductor.common.utils.TaskUtils)2 Configuration (com.netflix.conductor.core.config.Configuration)2