本文介绍了输入和输出的基本知识,您可以参见本文示例进行操作。
流程和步骤
通常流程的多个步骤之间需要传递数据。和函数式编程语言类似,FDL的步骤类似于函数,它接受输入(Input),并返回输出(Output),输出会保存在父步骤(调用者)的本地(Local)变量里。其中,输入和输出的类型必须是JSON对象格式,本地变量的类型因步骤而异。例如任务步骤把调用函数计算函数的返回结果作为本地变量,并行步骤把它所有分支的输出(数组)作为本地变量。步骤的输入、输出和本地变量总大小不能超过32 KiB,否则会导致流程执行失败。
如果一个步骤包含另一个步骤,则称外层步骤为父步骤,被包含步骤为子步骤。最外层步骤的父步骤是流程。如果两个步骤的父步骤相同,则这两个步骤是同级步骤。
流程和步骤都有输入、输出和本地变量。他们的转换关系如下:
- 步骤输入映射(
inputMappings
)将父步骤的输入和本地变量映射为子步骤的输入。 - 步骤输出映射(
outputMappings
)将当前步骤的输入和本地变量映射为当前步骤的输出。 - 流程输入映射(
inputMappings
)将用户执行流程时的输入映射为流程的输入。 - 流程输出映射(
outputMappings
)将流程输入和本地变量映射为流程的输出。
一个父步骤的本地变量保存了其所有子步骤输出的合并,如果输出中有同名键值,则后执行步骤会覆盖前执行步骤的结果。在大多数情况下,您不需要指定输入和输出映射,而使用默认的映射行为。他们的转换关系如下:
- 在不指定输入映射情况下,子步骤的输入是其父步骤输入和父步骤本地变量的合并(如果本地变量和输入有同名键值,则本地变量会覆盖输入)。
- 在不指定输出映射情况下,除并行步骤和并行循环步骤外的其它步骤都会将本地变量作为输出。
如果您想更好地控制输入和输出,则需要了解详细的映射规则。
下面示例流程的输入输出映射如图所示。其中step1是step2和step3的父步骤。step1和step4是最外层步骤。
version: v1
type: flow
steps:
- type: parallel
name: step1
branches:
- steps:
- type: pass
name: step2
- steps:
- type: pass
name: step3
- type: pass
name: step4
为了便于理解,这些映射可以用下面的代码描述。
func flow(input0 Input) (output0 Output) {
local0 := {}
input1 := buildInput(step1InputMappings, input0, local0)
output1 := step1(input1)
save(local0, output1)
input4 := buildInput(step4InputMappings, input0, local0)
output4 := step4(input4)
save(local0, output4)
return buildOutput(flowOutputMappings, input0, local0)
}
func step1(input1 Input) (output1 Output) {
local10 := {}
input2 := buildInput(step2InputMappings, input1, local10)
output2 := step2(input2)
save(local10, output2)
local11 := {}
input3 := buildInput(step3InputMappings, input1, local11)
output3 := step3(input3)
save(local11, output3)
return buildOutput(step1OutputMappings, [local10, local11])
}
func step2(input2 Input) (output2 Output) {
}
func step3(input3 Input) (output3 Output) {
}
func step4(input4 Input) (output4 Output) {
}
在这个例子中,流程包含了两个子步骤:step1
和step4
。step1
是一个并行步骤,它包含step2
和step3
两个子步骤。
- 系统在开始执行流程时,根据流程的输入映射将
StartExecution
输入转换为流程输入(input0
)。 - 在
flow
开始时,其local0
为空。 - 系统根据
step1
的输入映射(step1InputMappings
)来为它准备输入input1
,映射的源来自flow
的输入input0
和本地变量local0
。 - 调用
step1
,传入输入input1
,step1
返回输出output1
。- 在
step1
开始时,其local0
为空 。因为step1
是一个并行步骤,所以每个分支都对应一个本地变量,从而避免并发访问的问题。 - 系统根据
step2
的输入映射(step2InputMappings
)来为它准备输入input2
,映射的源来自step1
的输入input1
和本地变量local10
。 - 调用
step2
,传入输入input2
,step2
返回输出output2
。 - 系统将
step2
的输出保存到step1
的本地变量local10
。 - 同样的,系统调用
step3
并将结果保存在step1
的本地变量local11
。
- 在
- 系统将
step1
的输出保存到flow
的本地变量local0
。 - 类似的,系统根据
step4
的输入映射来为它准备输入input4
,映射的源来自flow
的输入input0
和本地变量local0
。说明 这时的本地变量local0
可能已经包含了step1
的输出,从而实现了step1
和step4
的数据传递。 - 调用
step4
,传入输入input4
,step4
返回输出output4
。 - 系统将
step4
的输出保存到flow
的本地变量local0
。 - 最后,系统根据流程的输出映射将
local0
转换为流程输出。
类型定义
输入映射和输出映射都是由target
和source
组成的数组类型,其中source
定义了参数来源,根据不同的映射取值不同,例如$input.key
表示参数来自输入input
的$.key
所对应的值,target
定义了目标参数名称。 当source
以$
开始表示该值通过JSON Path方式指定(可以通过这个工具调试JSON Path),系统会根据该路径解析为具体值,否则认为该值是常量类型。
- 来源(Source)
来源支持使用常量作为
source
值,可以使用数字(number
)、字符串(string
)、布尔(boolean
)、数组(array
)、对象(object
)或者null
类型。下面示例映射的source使用了不同类型的常量,其产生的输出如下所示。
outputMappings: - target: int_key source: 1 - target: bool_key source: true - target: string_key source: abc - target: float_key source: 1.234 - target: null_key source: null - target: array1 source: [1, 2, 3] - target: array2 source: - 1 - 2 - 3 - target: object1 source: {a: b} - target: object2 source: a:
{ "array1": [1, 2, 3], "array2": [1, 2, 3], "bool_key": true, "float_key": 1.234, "int_key": 1, "null_key": null, "object1": { "a": "b" }, "object2": { "a": "b" }, "string_key": "abc" }
- 目标
目标只能是一个字符串类型常量。
输入映射
输入映射将父步骤的输入($input
)、父步骤的本地变量($local
)、或者常量转换为子步骤的输入。如果没有指定输入映射,父步骤的输入和父步骤的本地变量合并后会被当做子步骤的输入。如果父步骤的输入和父步骤的本地变量中有相同名称,则新的输入中采用本地变量中的名或值。
inputMappings:
- target: key1
source: $input.key1
- target: key2
source: $local.key2
- target: key3
source: literal
输入 $input | 本地变量 $local | 输入映射 | 子步骤输入 |
|
|
|
|
|
| 无 |
|
|
| 无 |
|
输出映射
输出映射将当前步骤的输入($input
)、本地变量($local
)、或者常量转换为本地步骤的输出。如果没有指定输出映射,对于选择步骤和循环步骤,它们的本地变量会被当做其输出,任务步骤会将具体任务执行结果作为输出。由于并行(Parallel)和并行循环(ForEach)步骤的本地变量是数组类型,所以您需要定义输出映射将数组转换结果成JSON对象格式,默认不会输出它们的本地变量。具体介绍可参见步骤描述。
outputMappings:
- target: key1
source: $input.key1
- target: key2
source: $local.key2
- target: key3
source: literal
输入 $input | 本地变量 $local | 输出映射 | 步骤输出 |
|
|
|
|
|
|
|
|
|
| 无 |
|
输出如何保存到父步骤本地变量
子步骤的输出($output
)会被并入父步骤的本地变量。如果二者有重复名称,则输出中的名或值会覆盖本地变量相应名或值。
输出 $output | 父步骤本地变量 $local | 更改后父步骤本地变量 |
|
|
|
|
|
|