循环遍历
由于VO语言是面向数据集的,其所有隐含的语义中都已经带有了遍历并计算的数据逻辑。因此,VO语言只提供了一种支持循环语法的算子--Loop算子。
Loop算子
Loop算子是一个容器算子,其可以实现对其内部子流程的循环迭代运行。但Loop算子有一个强使用限定,就是其必须有前置算子向其传输数据流。
Loop算子驱动内嵌流程迭代执行。迭代次数可由“迭代次数”参数进行设置。若迭代次数设置为小于1的参数,那么内嵌流程必须有逻辑结束迭代操作。此时,内嵌流程必须有数据分支连接了退出端口。Loop算子会对该逻辑进行检查。
上图表示了一个迭代复制数据集的逻辑。每次循环都会复制一个数据集,并将数据集通过数据输出端口输出。也可以编写逻辑只在迭代结束后输出数据,这时候就需要内嵌流程不是去连接数据输出端口了,而是去连接退出端口了。Loop算子的退出端口一旦接受到数据集就会退出迭代,所以需要控制好何时向退出端口写出数据。若即连接了退出端口又设置了迭代次数,那么哪个条件先满足,就用哪个条件退出迭代。
使用Loop算子有一个特别需要注意的事项就是,内嵌流程必须与输入端口与迭代输出端口有连接。进入Loop算子的每个数据集都会激活一次迭代计算。首次迭代时,内嵌流程收到的数据集来自前置算子,迭代过程中再次收到的数据则来自内嵌流程的上一迭代的输出了。这样,内嵌流程就可以实现对同一数据集的多次迭代计算了。
异常
目前,绝大多数通用语言都支持这种语法特性,用于简化容错处理,确保未知运行错误可被捕获并恢复运行环境或进入错误处置。VO 语言也对该特性进行了支持,方便开发者编写复杂的数据流程。
异常捕获
异常捕获算子(ExceptionReporter)是一个容器算子。从其内部看,是一个可以容纳内嵌流程的标准容器算子。可以编写任意逻辑的流程。但是当流程发生错误,产生异常时,其不会立刻将异常抛回给VO语言解释器,由解释器结束这个数据流程;而是捕获异常,并将异常通过exceptionOut端口报出。可以在exceptionOut端口后加入异常信息处理逻辑,比如向Kafka同步异常状态等。
异常捕获算子有一个“是否异常退出”的控制参数,若该值为true。那么当异常发生且异常信息被成功写出到exceptionOut端口后,异常捕获算子会通知VO语言解释器终止整个流程的运行;若该值为false,那么数据流程会继续执行。流程执行的恢复点因算子功能差异会不同,可能会有以下几种情况:
-
算子忽略掉当前产生异常的数据,继续执行
-
算子忽略掉当前产生异常的数据集,继续执行
-
算子无法恢复执行,继续产生异常。
抛异常
在开发过程中,如果数据出现某个特征即认为不合理并需要退出整个流程时,可以使用抛异常算子。抛异常算子支持设置异常码和异常信息,用于记录数据的业务逻辑问题。异常信息支持以上下文变量的方式即@{varName},将输入端口输入的数据拼装进异常信息中。上下文变量的名字必须是输入数据集的列名,且只会将数据集的第一条信息作为代表拼装入异常信息。抛异常算子经常会与异常捕获算子搭配使用。