编排指令
指令概述
指令用于执行任务,只能写在start { } 模块中。编排指令本质上是DSL Script中的一个方法通常以任务或闭包做为参数,指示执行一个或一组任务。目前支持的指令有:
run基础执行,用于执行一个任务,并返回执行结果。when执行并判断,用于执行一个任务并根据任务结果进行判定,不同的结果进入不同的分支流程。async异步执行,以异步线程的方式执行一组任务,执行后该命令后流程会立即往下执行。
任务与任务组
指令参数通常是一个任务或任务组,任务通过任务名称的变量来表示,而任务组是以闭包的形式包裹若干其它任务执行指令。
start {
run task1 //1.执行任务
run { //2.执行任务组
run task2
run task3
}
}- 上例中第一个指令的参数是一个具体任务
task1 - 第2个指令参数是个任务组 ,该组内部包含了
task2与task3的执行 - 无论是任务还是任务组最终都会返回结果,任务组的结果是该组最后的执行的任务结果
- 任务组可以当作另一种形式的任务,后续文档中说参数为任务的时候就包括了任务组,除非文档中另作特殊说明。
run 指令
基础执行指令,用于执行一个任务,并返回执行结果。其语法如下:
run 任务名run指令仅接收一个任务做为参数run指令执行完成后会立即返回结果
基本示例
task1= CODE {"hello apiFlow"}
start {
run task1
}- 上例定义了一个脚本任务
task1 run指令执行了task1任务并返回执行结果- 由于
run task1是编排中最后一条指令其返回的结果将作为流程结果返回。
执行任务组
run 也可以执行一组任务,这些任务以闭包的方式包裹,语法如下:
run {
run 任务1
run 任务2
// ...其它
}- 在闭包中可以执行任意其它指令。
- 闭包中不能执行指令以外的代码如:
if、for等。 - 闭包中执行指令时可以继续嵌套其它任务组。
任务组示例
task1= CODE {"hello apiFlow1"}
task2= CODE {"hello apiFlow2"}
start {
run {
run task1
run task2
}
}- 上例流程最终返回
task2的结果,因为它是最后一个被执行的任务
when 判定指令
when 指令用于执行一个任务或任务组,然后根据返回的结果与状态进行条件判定,最后进入不同的流程分支。语法如下:
when 任务名 判定方法 分支任务1,分支任务2...when判断指令关键字- 任务名:指一个具体任务或任务组,任务的类型不做限制,但其返回结果的类型取决判定指令的要求
- 判定方法:指示如何进行判定的方法目前支持
isTrue、isFalse,isNull、notNull、isError、to - 分支任务:当判定条件成立或不成立时分别要进入的任务或任务组
- 返回结果:
when指令最后返回的结果取决于整条指令中最后执行的任务,包括条件任务。
when 基础示例
task1= BOOLE { true }
task2= CODE {"hello apiFlow"}
start {
when task1 isTrue task2
}- 上例
when指令先执行task1任务 - 接着
isTrue判定task1的返回结果是否为true就执行task2任务,否则就继续往下执行其它命令
isTrue 条件判定
布尔条件判定,接收一至两个分支任务做为参数,当when执行任务的结果为true 就行执行分支任务1,否则就执行分支2,如果分支2不存在不作任何处理。
when 条件任务 isTrue 分支任务1,分支任务2(可选)- 条件任务:该任务结果必须为布尔值,不能为空或其它类型,否则会报错。
- 分支任务1:条件任务的结果为
true时执行的任务或任务组,这是一个必填的参数。 - 分支任务2:条件任务的结果为
false时执行的任务或任务组,这是一个选填的参数。
isTrue 示例
task1= CODE { false }
task2= CODE {"hello apiFlow"}
task3= CODE {"welcome apiFlow"}
start {
when task1 isTrue task2,{
run task3
}
}先执行
task1返回结果为false,通常isTrue对应规范任务是BOOLE任务 但这不是必须的,只要任务的返回结果为布尔值就行。判定结果为
false执行第2个分支任务组isTrue为when指令缺省判定方法 可以直接省略如when task1,task2,task3与上面逻辑一至,但建议写上完整的判定方法语义更清晰
isFalse 条件判定
布尔条件判定,接收一至两个分支任务做为参数,当条件任务的结果为false 就行执行分支任务1,否则就执行分支2,如果分支2不存在不作任何处理。
when 条件任务 isFalse 分支任务1,分支任务2(可选)- 条件任务:该任务结果必须为布尔值,不能为空或其它类型,否则会报错。
- 分支任务1:条件任务的结果为
false时执行的任务或任务组,这是一个必填的参数。 - 分支任务2:条件任务的结果为
true时执行的任务或任务组,这是一个选填的参数。
isFalse 示例
task1= CODE { true }
task2= CODE {"hello apiFlow"}
task3= CODE {"welcome apiFlow"}
start {
when task1 isFalse task2,{
run task3
}
}先执行
task1返回结果为true,通常isFalse对应规范任务是BOOLE任务 但这不是必须的,只要任务的返回结果为布尔值就行。isFalse判定结果为true所以执行第2个分支任务组
isNull 条件判定
空值条件判定,接收一至两个分支任务做为参数,当when执行任务的结果为null时执行分支任务1,否则执行分支任务2。
when 条件任务 isNull 分支任务1,分支任务2(可选)- 条件任务:该任务结果可以是任意类型,包括
null值 - 分支任务1:条件任务的结果为
null时执行的任务或任务组,这是一个必填的参数 - 分支任务2:条件任务的结果不为
null时执行的任务或任务组,这是一个选填的参数
isNull 示例
task1 = CODE { null }
task2 = CODE { "value is null" }
task3 = CODE { "value is not null" }
start {
when task1 isNull task2, task3
}- 先执行
task1,返回结果为null isNull判定结果为true,因此执行分支任务1(即task2)- 如果
task1返回非空值,则会执行分支任务2(即task3)
notNull 条件判定
非空值条件判定,接收一至两个分支任务做为参数,当条件任务的结果不为null时执行分支任务1,否则执行分支任务2。
when 条件任务 notNull 分支任务1,分支任务2(可选)- 条件任务:该任务结果可以是任意类型,包括
null值 - 分支任务1:条件任务的结果不为
null时执行的任务或任务组,这是一个必填的参数 - 分支任务2:条件任务的结果为
null时执行的任务或任务组,这是一个选填的参数
notNull 示例
task1 = CODE { "hello" }
task2 = CODE { "value is not null" }
task3 = CODE { "value is null" }
start {
when task1 notNull task2, task3
}- 先执行
task1,返回结果为字符串"hello"(不为null) notNull判定结果为true,因此执行分支任务1(即task2)- 如果
task1返回null值,则会执行分支任务2(即task3)
isError 条件判定
错误状态判定,接收一至两个分支任务做为参数,当条件任务执行过程中发生错误时执行分支任务1,否则执行分支任务2。
when 条件任务 isError 分支任务1,分支任务2(可选)- 条件任务:该任务在执行过程中如果出现异常,则被认为是错误状态
- 分支任务1:条件任务执行出现错误时执行的任务或任务组,这是一个必填的参数
- 分支任务2:条件任务正常执行时执行的任务或任务组,这是一个选填的参数。
when指令最后返回的结果取决于指令中最后执行的任务,包括条件任务、分支任务1、分支任务2。
isError 示例
task1 = CODE { throw new Exception("error occurred") }
task2 = CODE { "task1 error" }
task3 = CODE { "task1 success" }
start {
when task1 isError task2, task3
}- 先执行
task1,task1抛出了一个异常 isError判定结果为真,因此执行分支任务1(即task2)- 如果
task1正常执行没有抛出异常,则会执行分支任务2(即task3),最后返回该任务结果
isError 注意事项
isError判定的是任务执行过程中的异常状态,而不是任务的返回值- 使用
isError可以优雅地处理任务执行失败的情况,避免整个流程因单个任务异常而中断
to 索引判定
to 方法用于根据条件任务返回的数字索引值来选择执行对应的分支任务。这是一种基于索引的多路分支判定方法。
when 条件任务 to 分支任务1, 分支任务2, 分支任务3, ...- 条件任务:该任务必须返回一个整数,该数字表示分支的索引(从0开始)。返回的数字必须在0到分支数减1的范围内,否则会报错。
- 分支任务:可以是一个或多个任务或任务组。分支任务的数量至少为一个,最多不限。根据条件任务返回的索引值,选择对应的分支任务执行。例如,索引0对应第一个分支任务,索引1对应第二个分支任务,以此类推。
- 条件任务推荐使用
CASE任务其返回的是状态的索引
to 基础示例
//0.状态A 1.状态B 2.状态C
task1 = CASE {
状态A= false
状态B= true
状态C= false
}
task2 = CODE { "执行分支0" }
task3 = CODE { "执行分支1" }
task4 = CODE { "执行分支2" }
start {
when task1 to task2, task3, task4
}- 先执行
task1,根据条件判断返回状态索引值1 - 然后根据索引值1,执行第二个分支任务即
task3
to 其它示例
task1 = CODE { 1 } // 直接返回索引1
task2 = CODE { "分支0" }
task3 = CODE { "分支1" }
task4 = CODE { "分支2" }
start {
when task1 to task2,{
run task3
run task4
}
}- 执行
task1返回1,然后执行第二个分支任务组 - 最后整体
when指令执行后返回结果是task4的结果,因为它最后被执行
to 使用规范与建议
- 索引范围:条件任务返回的数字必须在
[0, 分支数-1]范围内,否则会抛出索引越界异常 - 数字类型:返回的必须是整数
- 推荐使用CASE任务:
CASE任务天然适合返回索引值,语义清晰 - 分支数量:至少需要提供一个分支任务,否则语法错误
async 异步指令
指示任务或任务组脱离主线程来运行,语法如下:
async task1,task2..async接受多个任务或任务组做为参数,每个任务都以独立线程运行- 独立线程运行的任务的结果不能跨线程引用 因为不能确认任务的执行顺序。
async 复杂示例
start {
async task1,{
run task2
run task3
}
run task4
}上例总共有三个线程运行:
- 主线程:运行task4
- 子线程1:运行task1
- 子线程2: 运行task2、task3
exit 终止指令
exit 指令用于立即终止当前工作流的执行,并返回指定的结果。使用该指令后,流程会立即中断,不再执行后续的任何任务或指令。
exit 结果值exit终止指令关键字- 结果值:流程终止后返回的结果,可以是任意可序列化的数据(字符串、数字、Map、List等),也可以为
null - 该指令会立即中断流程,后续所有指令都不会执行
- 与抛出异常不同,
exit是一种正常的流程终止方式,不会记录错误日志
exit 基础示例
task1 = CODE { "步骤1完成" }
task2 = CODE { "步骤2完成" }
task3 = CODE { "步骤3完成" }
start {
run task1
exit "流程提前结束" // 立即终止流程
run task2 // 不会执行
run task3 // 不会执行
}- 执行
task1后,exit指令立即终止流程 - 流程最终返回字符串
"流程提前结束" task2和task3不会被执行
exit 条件终止示例
checkTask = BOOLE { input.skipProcess == true }
task1 = CODE { "正常处理" }
successTask = CODE { "处理成功" }
start {
when checkTask isTrue {
exit ([status: "skipped", message: "用户跳过处理"])
}
run task1
run successTask
}- 如果
checkTask返回true,则直接终止流程并返回跳过状态 - 否则继续执行后续的
task1和successTask exit返回的是一个Map结构,包含状态和消息信息
exit 与 ABORT 任务的区别
在早期版本中,ApiFlow 使用ABORT任务来终止流程,现在推荐使用exit指令替代:
// 旧方式(已废弃)
abortTask = ABORT { "终止原因" }
start {
run abortTask
}
// 新方式(推荐)
start {
exit "终止原因"
}主要区别:
ABORT是任务类型,需要先声明再执行exit是指令,可以直接在编排中使用exit语义更清晰,使用更简洁
exit 使用建议
- 返回值类型:确保返回的数据是可序列化的(实现
Serializable接口),避免使用不可序列化的对象 - 使用场景:适用于需要提前终止流程的场景,如:
- 前置条件不满足
- 检测到无需继续处理的情况
- 遇到业务规则要求提前返回
- 异常处理:如果是因为错误需要终止,建议抛出异常而不是使用
exit,这样可以记录错误日志便于排查问题 - 返回结构:建议返回结构化的数据(如Map),包含状态码、消息等信息,便于调用方识别终止原因
exit 注意事项
exit指令只能在start {}编排模块中使用- 异步任务中的
exit只会终止该异步线程,不影响主线程和其他异步线程 - 传递给
exit的参数必须是可序列化的,否则会抛出异常