private void failWorkflow(String errorMsg) { logger.error(errorMsg); throw new TerminateWorkflowException(errorMsg); } }
/** * Helper method that looks into the input params and returns the dynamic task name * * @param taskInput: a map which contains different input parameters and * also contains the mapping between the dynamic task name param and the actual name representing the dynamic task * @param taskNameParam: the key that is used to look up the dynamic task name. * @return The name of the dynamic task * @throws TerminateWorkflowException : In case is there is no value dynamic task name in the input parameters. */ @VisibleForTesting String getDynamicTaskName(Map<String, Object> taskInput, String taskNameParam) throws TerminateWorkflowException { return Optional.ofNullable(taskInput.get(taskNameParam)) .map(String::valueOf) .orElseThrow(() -> { String reason = String.format("Cannot map a dynamic task based on the parameter and input. " + "Parameter= %s, input= %s", taskNameParam, taskInput); return new TerminateWorkflowException(reason); }); }
private Integer getSubWorkflowVersion(Map<String, Object> resolvedParams, String subWorkflowName) { return Optional.ofNullable(resolvedParams.get("version")) .map(Object::toString) .map(Integer::parseInt) .orElseGet( () -> metadataDAO.getLatest(subWorkflowName) .map(WorkflowDef::getVersion) .orElseThrow(() -> { String reason = String.format("The Task %s defined as a sub-workflow has no workflow definition available ", subWorkflowName); logger.error(reason); return new TerminateWorkflowException(reason); })); } }
@VisibleForTesting SubWorkflowParams getSubWorkflowParams(WorkflowTask taskToSchedule) { return Optional.ofNullable(taskToSchedule.getSubWorkflowParam()) .orElseThrow(() -> { String reason = String.format("Task %s is defined as sub-workflow and is missing subWorkflowParams. " + "Please check the blueprint", taskToSchedule.getName()); logger.error(reason); return new TerminateWorkflowException(reason); }); }
@VisibleForTesting void failTask(Task task, PayloadType payloadType, String errorMsg) { logger.error(errorMsg); task.setReasonForIncompletion(errorMsg); task.setStatus(Task.Status.FAILED_WITH_TERMINAL_ERROR); if (payloadType == PayloadType.TASK_INPUT) { task.setInputData(null); } else { task.setOutputData(null); } throw new TerminateWorkflowException(errorMsg, Workflow.WorkflowStatus.FAILED, task); }
/** * This method gets the TaskDefinition for a specific {@link WorkflowTask} * * @param taskToSchedule: An instance of {@link WorkflowTask} which has the name of the using which the {@link TaskDef} can be retrieved. * @return An instance of TaskDefinition * @throws TerminateWorkflowException : in case of no workflow definition available */ @VisibleForTesting TaskDef getDynamicTaskDefinition(WorkflowTask taskToSchedule) throws TerminateWorkflowException { //TODO this is a common pattern in code base can be moved to DAO return Optional.ofNullable(taskToSchedule.getTaskDefinition()) .orElseGet(() -> Optional.ofNullable(metadataDAO.getTaskDef(taskToSchedule.getName())) .orElseThrow(() -> { String reason = String.format("Invalid task specified. Cannot find task by name %s in the task definitions", taskToSchedule.getName()); return new TerminateWorkflowException(reason); })); } }
private void populateVersionForSubWorkflow(WorkflowTask workflowTask) { SubWorkflowParams subworkflowParams = workflowTask.getSubWorkflowParam(); if (subworkflowParams.getVersion() == null) { String subWorkflowName = subworkflowParams.getName(); Integer subWorkflowVersion = metadataDAO.getLatest(subWorkflowName) .map(WorkflowDef::getVersion) .orElseThrow( () -> { String reason = String.format("The Task %s defined as a sub-workflow has no workflow definition available ", subWorkflowName); logger.error(reason); return new TerminateWorkflowException(reason); } ); subworkflowParams.setVersion(subWorkflowVersion); } }
private boolean isTaskSkipped(WorkflowTask taskToSchedule, Workflow workflow) { try { boolean isTaskSkipped = false; if (taskToSchedule != null) { Task t = workflow.getTaskByRefName(taskToSchedule.getTaskReferenceName()); if (t == null) { isTaskSkipped = false; } else if (t.getStatus().equals(SKIPPED)) { isTaskSkipped = true; } } return isTaskSkipped; } catch (Exception e) { throw new TerminateWorkflowException(e.getMessage()); } }
/** * This method is used to get the List of dynamic workflow tasks and their input based on the {@link WorkflowTask#getDynamicForkTasksParam()} * * @param taskToSchedule: The Task of type FORK_JOIN_DYNAMIC that needs to scheduled, which has the input parameters * @param workflowInstance: The instance of the {@link Workflow} which represents the workflow being executed. * @param dynamicForkTaskParam: The key representing the dynamic fork join json payload which is available in {@link WorkflowTask#getInputParameters()} * @throws TerminateWorkflowException : In case of input parameters of the dynamic fork tasks not represented as {@link Map} * @return a {@link Pair} representing the list of dynamic fork tasks in {@link Pair#getLeft()} and the input for the dynamic fork tasks in {@link Pair#getRight()} */ @SuppressWarnings("unchecked") @VisibleForTesting Pair<List<WorkflowTask>, Map<String, Map<String, Object>>> getDynamicForkTasksAndInput(WorkflowTask taskToSchedule, Workflow workflowInstance, String dynamicForkTaskParam) throws TerminateWorkflowException { Map<String, Object> input = parametersUtils.getTaskInput(taskToSchedule.getInputParameters(), workflowInstance, null, null); Object dynamicForkTasksJson = input.get(dynamicForkTaskParam); List<WorkflowTask> dynamicForkWorkflowTasks = objectMapper.convertValue(dynamicForkTasksJson, ListOfWorkflowTasks); for (WorkflowTask workflowTask : dynamicForkWorkflowTasks) { if (MetadataMapperService.shouldPopulateDefinition(workflowTask)) { workflowTask.setTaskDefinition(metadataDAO.getTaskDef(workflowTask.getName())); } } Object dynamicForkTasksInput = input.get(taskToSchedule.getDynamicForkTasksInputParamName()); if (!(dynamicForkTasksInput instanceof Map)) { throw new TerminateWorkflowException("Input to the dynamically forked tasks is not a map -> expecting a map of K,V but found " + dynamicForkTasksInput); } return new ImmutablePair<>(dynamicForkWorkflowTasks, (Map<String, Map<String, Object>>) dynamicForkTasksInput); }
String reason = String.format("Dynamic tasks could not be created. The value of %s from task's input %s has no dynamic tasks to be scheduled", dynamicForkJoinTaskParam, input); logger.error(reason); throw new TerminateWorkflowException(reason);
throw new TerminateWorkflowException("No tasks found to be executed", WorkflowStatus.COMPLETED); 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); });
throw new TerminateWorkflowException("Dynamic join definition is not followed by a join task. Check the blueprint");
@VisibleForTesting void checkForTimeout(TaskDef taskDef, Task task) { if (taskDef == null) { LOGGER.warn("missing task type " + task.getTaskDefName() + ", workflowId=" + task.getWorkflowInstanceId()); return; } if (task.getStatus().isTerminal() || taskDef.getTimeoutSeconds() <= 0 || !task.getStatus().equals(IN_PROGRESS)) { return; } long timeout = 1000L * taskDef.getTimeoutSeconds(); long now = System.currentTimeMillis(); long elapsedTime = now - (task.getStartTime() + ((long) task.getStartDelayInSeconds() * 1000L)); if (elapsedTime < timeout) { return; } String reason = "Task timed out after " + elapsedTime + " millisecond. Timeout configured as " + timeout; Monitors.recordTaskTimeout(task.getTaskDefName()); switch (taskDef.getTimeoutPolicy()) { case ALERT_ONLY: return; case RETRY: task.setStatus(TIMED_OUT); task.setReasonForIncompletion(reason); return; case TIME_OUT_WF: task.setStatus(TIMED_OUT); task.setReasonForIncompletion(reason); throw new TerminateWorkflowException(reason, WorkflowStatus.TIMED_OUT, task); } }
.orElseThrow(() -> { String reason = String.format("Invalid task specified. Cannot find task by name %s in the task definitions", taskToSchedule.getName()); return new TerminateWorkflowException(reason); }));
throw new TerminateWorkflowException("Dynamic join definition is not followed by a join task. Check the blueprint");
.orElseThrow(() -> { String reason = String.format("Invalid task specified. Cannot find task by name %s in the task definitions", taskToSchedule.getName()); return new TerminateWorkflowException(reason); }));
.orElseThrow(() -> { String reason = String.format("Invalid task. Task %s does not have a definition", taskToSchedule.getName()); return new TerminateWorkflowException(reason); });
WorkflowStatus status = task.getStatus().equals(TIMED_OUT) ? WorkflowStatus.TIMED_OUT : WorkflowStatus.FAILED; updateWorkflowOutput(workflow, task); throw new TerminateWorkflowException(task.getReasonForIncompletion(), status, task);
@VisibleForTesting SubWorkflowParams getSubWorkflowParams(WorkflowTask taskToSchedule) { return Optional.ofNullable(taskToSchedule.getSubWorkflowParam()) .orElseThrow(() -> { String reason = String.format("Task %s is defined as sub-workflow and is missing subWorkflowParams. " + "Please check the blueprint", taskToSchedule.getName()); logger.error(reason); return new TerminateWorkflowException(reason); }); }
@VisibleForTesting void failTask(Task task, PayloadType payloadType, String errorMsg) { logger.error(errorMsg); task.setReasonForIncompletion(errorMsg); task.setStatus(Task.Status.FAILED_WITH_TERMINAL_ERROR); if (payloadType == PayloadType.TASK_INPUT) { task.setInputData(null); } else { task.setOutputData(null); } throw new TerminateWorkflowException(errorMsg, Workflow.WorkflowStatus.FAILED, task); }