输入和输出
概述
工作流开始运行时,会接收用户指定的输入数据,并将数据传递至工作流的开始节点,即 start
所指向的节点。在后续的执行中,每个节点都接收上一个节点的输出作为自己的输入,并在执行结束后,继续将自己的输出传给下一个节点。所有的输入输出数据均为 JSON 格式。本节将为您介绍如何处理节点的输入输出数据。
工作流的输入与输出
- workflow 的输入由用户提供,如果用户未提供输入,那么使用
"{}"
作为默认输入。 - workflow 的输出是最后一个节点的输出。
节点的输入与输出
workflow 的输入作为 start 节点的输入,当一个节点执行结束后,它的输出会成为下一个节点的输入。
节点可以通过 stateDataFilter
处理上一个节点传入的输入数据,和传给下一个节点的输出数据。operation 节点还可以通过 actionDataFilter
定义调用云函数时的输入,和处理云函数的返回结果,比如把节点输入数据的其中一部分作为 payload 去调用云函数,云函数返回结果后只取出其中的一部分放入节点数据里。
stateDataFilter
和 actionDataFilter
都是节点的可选参数,节点若不定义则不对输入输出做其它处理。
stateDataFilter
参数 | 类型 | 描述 |
---|---|---|
input(可选) | string | jq 表达式,在执行 state 前过滤输入 |
output(可选) | string | jq 表达式,在 state 结束前过滤输出 |
示例:
工作流的定义如下
name: demo
start: hello
description: "从输入数据中取出 apple 对应的值"
states:
- type: wait
name: hello
stateDataFilter:
input: ".fruits"
output: "{res: .apple}"
seconds: 2
end: true
假定工作流的输入数据为
{
"fruits": {
"apple": 7,
"banana": 10
},
"vegetables": ["potato", "tomato", "carrot"]
}
工作流的处理流程如下:
1、收到执行请求和输入数据,找到开始节点 hello,将数据传递给 hello;
2、hello 根据 stateDataFilter
的 input
参数处理输入数据,处理结果作为自己节点数据,结果为
{
"apple": 7,
"banama" : 10
}
3、hello 节点执行 wait 逻辑,等待2秒钟;
4、hello 节点操作结束,根据 stateDataFilter
的 output
参数处理输出数据,结果为
{
"res": 7
}
5、由于 hello 节点之后没有其它节点,因次 hello 执行结束后整个工作流就结束了,工作流的输出即上一步中的结果。
actionDataFilter
在 operation 节点中调用函数计算等公有云服务时,可以通过这个 filter 定义传给云服务的参数,也能对服务返回的结果进一步提取筛选,并加入到节点数据中。
参数 | 类型 | 描述 |
---|---|---|
fromStateData(可选) | string | jq 表达式,从节点数据中过滤部分数据传给云服务 |
results(可选) | string | jq 表达式,对调用云服务返回的结果进一步过滤,筛选出想要的数据 |
toStateData(可选) | string | jq 表达式,把 results 的结果添加/合并到 state data 的某个字段内, 若未指定则放入节点数据的顶层 |
useResults(可选) | bool | 是否把云服务返回的结果放入节点数据内,默认为 true |
示例:
name: demo
start: hello
description: "从输入数据中取出 apple 对应的值"
states:
- type: operation
name: hello
actionDataFilter:
fromStateData: "{ stateInput: .hello }"
results: "[ .breads[0], .pasta[1] ]"
toStateData": ".itemsToBuyAtStore"
resource: "brn:cfc:bj:123456:function:test:$LATEST"
end: true
假定本次工作流的输入为{"hello":"world"}
,函数的返回为
{
"breads": ["baguette", "brioche", "rye"],
"pasta": [ "penne", "spaghetti", "ravioli"]
}
那么工作流的处理流程大致如下:
1、收到执行请求和输入数据,找到开始节点 hello,将输入数据 {"hello":"world"}
传递给 hello;
2、hello 节点内没有定义 stateDataFilter
,因此不执行输入预处理;
3、hello 节点内定义了 actionDataFilter
,根据 fromStateData
参数执行数据处理,得到 {"stateInput": "world"}
;
4、hello 节点将上一步得到的结果作为 payload 去调用函数;
5、函数返回结果后,根据 actionDataFilter
的 results
参数处理函数返回,结果为 ["baguette", "spaghetti"]
;
6、根据 actionDataFilter
的 toStateData
参数继续处理,把 results
的结果放到节点数据的 itemsToBuyAtStore
字段(没有则创建),最终节点数据为
{
"hello": "world",
"itemsToBuyAtStore": ["baguette", "spaghetti"]
}
7、hello 节点内没有定义 stateDataFilter
,因此不执行输出预处理,工作流执行结束。
jq 表达式
从上文的介绍中可知,节点数据的过滤、处理都依靠 jq 表达式,这里展示出常用的 jq 操作。源数据如下:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
各类操作结果如下:
表达式 | 结果 |
---|---|
.store | store 内的所有数据 |
.store.bicycle.price | store 内 bicycle 的价格 |
{color: .store.bicycle.color} | {"color": "red"} |
.store.book[2] | store 内的第3个book对象 |
.store.book[0:2] | store 内的前两本书 |
.store.book[] | select(.price < 10) | store 内所有价格小于10的book |
.store.book[].author | store 内的所有书的作者 |
jq 是一个功能强大的、用于解析 json 数据的工具,关于 jq 的更多用法,您可参考