1. 交互流程
- 用户定义task Definition:Worker通过自己的name和task的name比对,确认是否处理此任务。
- 用户定义workflow,引用之前定义的taskDefinition。此时用户需要定义task的入参和出参。
- 用户启动worker,等待执行任务。
- 用户执行workflow。需要定义workflow的入参和出参。
- workflow执行完成,用户可查看执行结果。
2. 定义input output
conductor的task分为两种:系统定义task和用户定义task。
系统定义task是为了完成工作流的组织和流转。
用户定义task 是为了完成用户定义的功能。
工作流中的task,必须要先定义。
task definition中定义task支持哪些输入和输出的名字:inputKeys,outputKeys。
工作流中引用task的时候,定义task的入参inputParameters。
工作流定义的时候,可以指定工作流的输入inputParameters和输出outputParameters。如果没有指定输出,则默认采用最后一个任务的输出,作为整体工作流的输出。
conductor的出参和入参定义非常灵活。task的inputparameters是一个json字段。其中的值可以包含来自workflow入参的引用以及其他task运行结果的引用。
引用的格式:${SOURCE.input/output.JSONPath}
SOURCE |
可以为"workflow"或者其他task的referenceName |
input/output |
SOURCE字段的输入或输出 |
JSONPath |
json路径。 |
下面是官网给出的实例。其中包括了怎样从工作流引用入参,从task引用出参,以及定义固定值。
{
"inputParameters": {
"movieId": "${workflow.input.movieId}",
"url": "${workflow.input.fileLocation}",
"lang": "${loc_task.output.languages[0]}",
"http_request": {
"method": "POST",
"url": "http://example.com/${loc_task.output.fileId}/encode",
"body": {
"recipe": "${workflow.input.recipe}",
"params": {
"width": 100,
"height": 100
}
},
"headers": {
"Accept": "application/json",
"Content-Type": "application/json"
}
}
}
}
3. 代码实现分析
当有任务执行结束后,会调用server的updateTask rest接口。server会根据workflow的流程,再次发布需要执行的task。task的入参会被填充。ParametersUtil负责解析和填充参数。
下面是server填充参数的代码。conductor提取了workflow的输入和输出,以及workflow的一些其他属性值。conductor还提取了workflow所有任务的输入输出以及任务的属性值。所以在task定义中,我们可以引用下面所有的属性。
public Map getTaskInputV2(Map input, Workflow workflow, String taskId, TaskDef taskDef) {
......
Map wf = new HashMap<>();
wf.put("input", workflow.getInput());
wf.put("output", workflow.getOutput());
wf.put("status", workflow.getStatus());
wf.put("workflowId", workflow.getWorkflowId());
wf.put("parentWorkflowId", workflow.getParentWorkflowId());
wf.put("parentWorkflowTaskId", workflow.getParentWorkflowTaskId());
wf.put("workflowType", workflow.getWorkflowType());
wf.put("version", workflow.getVersion());
wf.put("correlationId", workflow.getCorrelationId());
wf.put("reasonForIncompletion", workflow.getReasonForIncompletion());
wf.put("schemaVersion", workflow.getSchemaVersion());
inputMap.put("workflow", wf);
workflow.getTasks().stream().map(Task::getReferenceTaskName).map(taskRefName -> workflow.getTaskByRefName(taskRefName)).forEach(task -> {
Map taskIO = new HashMap<>();
taskIO.put("input", task.getInputData());
taskIO.put("output", task.getOutputData());
taskIO.put("taskType", task.getTaskType());
if(task.getStatus() != null) {
taskIO.put("status", task.getStatus().toString());
}
taskIO.put("referenceTaskName", task.getReferenceTaskName());
taskIO.put("retryCount", task.getRetryCount());
taskIO.put("correlationId", task.getCorrelationId());
taskIO.put("pollCount", task.getPollCount());
taskIO.put("taskDefName", task.getTaskDefName());
taskIO.put("scheduledTime", task.getScheduledTime());
taskIO.put("startTime", task.getStartTime());
taskIO.put("endTime", task.getEndTime());
taskIO.put("workflowInstanceId", task.getWorkflowInstanceId());
taskIO.put("taskId", task.getTaskId());
taskIO.put("reasonForIncompletion", task.getReasonForIncompletion());
taskIO.put("callbackAfterSeconds", task.getCallbackAfterSeconds());
taskIO.put("workerId", task.getWorkerId());
inputMap.put(task.getReferenceTaskName(), taskIO);
});
Configuration option = Configuration.defaultConfiguration().addOptions(Option.SUPPRESS_EXCEPTIONS);
DocumentContext io = JsonPath.parse(inputMap, option);
Map replaced = replace(inputParams, io, taskId);
return replaced;
}
- 总结
conductor提供了json的入参格式,可以定义复杂的入参。
conductor提供了task之间,以及workflow和task之间的参数引用。
conductor的task可以引用其他task的入参出参,但是没有根据参数引用强制task的执行顺序。task的执行还是按照工作流的定义进行。