原理

核心架构

OOCANA 是一个高效的工作流调度引擎,用于对一系列任务单元进行编排与执行。其架构由两个核心文件组成:

  • flow.oo.yaml:存储任务调度逻辑(以下简称 flow
  • block.oo.yaml:定义执行单元所需的内容(以下简称 block

block.oo.yaml 中包含指向执行代码的引用,这些代码我们称为 block 函数

block 函数可以使用 NodeJS 或 Python 语言实现。函数名必须为 main,接收两个参数:

  1. 输入数据对象
  2. 运行时提供的辅助函数集

开发者可通过第一个参数获取输入数据,并返回一个字典对象(在 NodeJS 中可以是 Promise<Object>)作为 block 的输出。

flow 文件则定义了 block 间的执行顺序与数据流动关系。

block 的编排与执行机制

OOCANA 采用数据流驱动模式,block 的触发顺序由 flow 中定义的连线决定。当一个 block 所需的数据准备就绪时,该 block 会被自动触发执行。这与 GitHub Action 中的事件驱动方式(上一步完成后触发下一步)有所不同,后者更适用于编译、打包等 CI/CD 场景。

运行环境与执行器

目前,block 支持 NodeJS 和 Python 两种运行环境。每个运行环境都有相应的执行器来加载和执行 block 代码。

关键执行特性:

  • 同语言 block 默认在同一个运行环境中运行
  • 同进程优化: 当连续的 block 使用相同语言且属于同一包时,OOCANA 会将它们放在同一进程中以减少开销
  • 独立进程: 可以配置 block 在独立进程中运行,以实现隔离或调试目的

有关执行器和进程管理的详细信息,请参阅执行器概念

block 之间的数据传递

不同语言环境之间的数据传递通过 JSON 实现,而同一语言环境内的 block 可以通过 JSON 或直接变量引用传递数据。

JSON 序列化(跨语言或跨进程):

  • 所有支持的语言之间的通用兼容性
  • 用于 block 在不同语言或独立进程中运行时
  • 序列化/反序列化有轻微的性能开销
  • 除变量类型外的所有接口类型都可以缓存

直接变量传递(同语言、同进程):

  • 最高性能,零序列化开销
  • 通过变量类型接口使用
  • 可以传递无法序列化的复杂对象
  • 变量采用引用传递机制 - 一个 block 修改变量值会影响其他 block 中的同一变量
  • 无法缓存(上游 block 将始终重新执行)
信息

使用变量类型接口以获得最高性能时,请注意 block 会变得紧密耦合,只能与同一语言环境中的 block 一起工作。这会降低 block 的可移植性,但为复杂对象传递提供了显著的性能优势。

数据接口规范

block 和 flow 分别定义了输入输出数据的格式规范。目前 OOCANA 运行时不会对这些数据格式进行运行时校验(GUI 图形界面的部分组件会执行静态校验)。因此,开发者需自行确保 block 函数返回的数据结构符合 flow 和 block 中定义的接口规范。

调试优化策略

当工作流中包含大量 block 且执行耗时较长时,可采用以下策略加速调试过程:

  1. 终止点策略:指定目标 block,执行到该 block 后立即结束运行
  2. 缓存策略:利用之前执行的数据缓存(仅支持 JSON 数据),跳过无需重新执行的 block,快速到达指定 block