API: wingman.orchestration
工作流模块,提供工作流提交、依赖调度、取消与查询功能。
模块概述
orchestration 模块在 runtime 内本地执行工作流:
- 提交工作流 - 校验依赖图(环检测)后立即返回工作流 ID;单调度线程做调度决策,就绪任务派发到独立 worker 线程执行
- 依赖调度 - 前置任务全部成功才调度后置任务;前置失败/取消/超时沿依赖图传播跳过
- 条件分支 - 任务可带
when条件,前置满足后求值,不成立按条件链跳过(不判工作流失败) - 并发控制 -
maxParallel约束工作流内同时执行的任务数(默认 1 串行) - 取消工作流 - 取消执行中的工作流(协作式取消,未开工任务直接取消)
- 查询工作流 - 获取工作流与任务级状态快照(含依赖阻塞态)
注意
任务 run 与条件 when 均在调度线程/worker 线程上调用,必须是线程安全可调用体—— Python 函数满足(GIL),Lua 函数提交即拒绝(同 task.submit 的 async 门控语义)。
提交工作流
submit_workflow(workflow)
说明:提交一个新的工作流执行。立即返回工作流 ID;调度线程按依赖序派发就绪任务到 worker 线程,工作流内并发度受 maxParallel 约束(默认 1 = 串行)。两端函数名一致(均为 snake_case)。
函数签名:
submit_workflow(workflow: dict) -> str | Nonesubmit_workflow(workflow: table) -> string | nil参数:
workflow- 工作流定义对象:name(string,可选) - 工作流名称maxParallel(int,可选) - 工作流级并发上限:同时执行中的任务数,默认 1(串行);<1拒绝tasks(array,必填,非空) - 任务定义数组,每个任务:id(string,必填) - 任务唯一标识(重复即拒绝)run(callable,必填) - 任务执行体(须线程安全可调用体)dependsOn(array of string,可选) - 前置任务 id 集合;前置全部succeeded才调度本任务when(callable,可选) - 分支条件,前置满足后的调度点求值一次(详见下节)timeoutMs(int,可选) - 超时毫秒数,默认 30000maxRetries(int,可选) - 失败重试次数,默认 0backoffMs(int,可选) - 重试退避基准毫秒数,默认 500backoffFactor(float,可选) - 退避因子,默认 2.0
返回:
- Python: 工作流 ID,失败返回
None - Lua: 工作流 ID,失败返回
nil
拒绝规则(返回 None 并发出 orchestration.error 事件,负载 {"error": 原因}):
workflow非对象、tasks缺失/空数组、任务项缺id/run或类型不符maxParallel非整数或< 1- 重复任务 id
- 未知前置引用、自依赖、依赖环(DFS 环检测,提交即拒绝)
run/when非线程安全可调用体(Lua 函数)
from wingman import orchestration
workflow_id = orchestration.submit_workflow({
"name": "daily_report",
"tasks": [
# 无 dependsOn 的任务即入口任务
{"id": "collect", "run": collect_data},
{"id": "analyze", "run": analyze, "dependsOn": ["collect"]},
# 多前置:b、c 都成功后才执行 d
{"id": "render", "run": render, "dependsOn": ["analyze"]},
{"id": "upload", "run": upload, "dependsOn": ["analyze", "render"]},
]
})
if workflow_id is None:
print("提交被拒绝,原因见 orchestration.error 事件")条件分支(when)
任务项可选 when 谓词实现分支过滤。语义与依赖传播/重试对齐:
- 求值时机 - 前置任务全部
succeeded后、开工前的调度点求值一次(不随重试重复);谓词在锁外求值,可重入get_workflow/cancel_workflow - 真值口径(跨语言统一):
| 返回值 | 判定 |
|---|---|
bool | 按值 |
int / float | 非 0 为真 |
str | 非空为真 |
list / dict | 非空为真 |
None | 假 |
- 不成立 → 条件链
skipped:分支过滤是正常控制流,不判工作流失败;后置任务沿依赖图连锁跳过,混合前置时失败链优先于条件链 - 求值异常 → 按失败落账:任务置
failed并携带错误信息when predicate threw: ...(沿用 task 模块失败语义),后置按失败链传播
import wingman.orchestration as orch
def publish():
... # 正式发布
def dry_run():
... # 演练
orch.submit_workflow({
"tasks": [
{"id": "build", "run": build},
# 两个分支互斥:由 flag 决定走哪边
{"id": "publish", "run": publish, "dependsOn": ["build"],
"when": lambda: release_flag},
{"id": "dry_run", "run": dry_run, "dependsOn": ["build"],
"when": lambda: not release_flag},
]
})
# 只有一条分支执行,另一条 skipped;工作流终态 succeeded注意
when 与 run 同门控:必须线程安全可调用体,Lua 函数提交即拒绝。条件不成立 的分支不占 maxParallel 执行额度(求值即落账,不进 worker)。
取消工作流
cancel_workflow(workflowId)
说明:取消执行中的工作流。执行中任务协作式取消(run 内部无法被强制打断;快照即时反映 canceled,工作体自然返回后 worker 收尾);未开工任务(含依赖阻塞态)直接置 canceled。未知 ID 或已终局的工作流返回 false。
函数签名:
cancel_workflow(workflowId: str) -> boolcancel_workflow(workflowId: string) -> boolean返回:
- 是否发生取消转换
查询工作流
get_workflow(workflowId)
说明:获取工作流状态快照。快照读取不阻塞调度。
函数签名:
get_workflow(workflowId: str) -> dict | Noneget_workflow(workflowId: string) -> table | nil返回:工作流快照对象,不存在返回 None/nil。
get_all_workflows()
说明:获取所有工作流快照列表。
函数签名:
get_all_workflows() -> list[dict]get_all_workflows() -> table状态词汇表
工作流状态(status):
| 状态 | 含义 |
|---|---|
running | 存在未终局任务 |
succeeded | 全部任务 succeeded(或按条件链 skipped) |
failed | 存在失败链任务(failed/timeout 及其传播的 skipped)且无未终局任务 |
canceled | cancel_workflow 请求后定稿(执行中任务协作取消,worker 后台收尾) |
任务状态(tasks[].status):
| 状态 | 含义 |
|---|---|
blocked | 前置任务未全部成功(依赖阻塞态) |
pending | 前置已全部成功,等待调度 |
running | worker 执行中;协作取消即时反映 canceled(不等工作体返回) |
skipped | 失败链(前置 failed/canceled/timeout 传播)或条件链(when 不成立的分支过滤)连锁跳过,传递;快照不区分根因 |
canceled | 工作流取消时未开工的任务 |
succeeded / failed / timeout | 终态,语义同 wingman.task(重试额度内的失败不传播,恢复后照常调度后置) |
失败任务快照额外携带 error 字段(异常消息,同 task.error 语义)。
流程级事件
工作流生命周期经 EventHub 广播 orchestration.* 三类事件(source 均为 orchestration)。 全部由调度线程单点发出,全序与调度序一致:started → task_finished×N → finished。
| 事件 | 负载 | 时机 |
|---|---|---|
orchestration.started | {workflow, name} | 调度线程启动(提交成功即发) |
orchestration.task_finished | {workflow, task, status, error?} | 单个任务落账终态(status 为任务终态词,失败携带 error) |
orchestration.finished | {workflow, name, status, tasks} | 工作流定稿(status ∈ succeeded/failed/canceled) |
orchestration.finished 的 tasks 计数字段:
| 字段 | 口径 |
|---|---|
succeeded / failed / skipped / canceled | 按落账四态计数(failed 含 timeout) |
other | 取消窗口内执行中未收账的任务(仅此时出现;内核终态以快照为准) |
total | 任务总数(各字段之和) |
任务事件口径
- 失败链/条件链传播的
skipped任务不单发task_finished(未真实执行),只在finished计数可见;取消窗口执行中的任务同样不单发。 - 编排内任务的
task.*模块级事件关闭(emitEvents门控),可观测统一走本节orchestration.*,避免双通道重复。
from wingman import event_hub, orchestration
event_hub.subscribe("orchestration.finished",
lambda msg: print(msg.payload["status"], msg.payload["tasks"]),
"report-watcher")
workflow_id = orchestration.submit_workflow({"name": "daily_report", "tasks": [...]})工作流快照对象
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 工作流唯一 ID(wf-<N>) |
name | string | 工作流名称(未提供为空串) |
status | string | 工作流状态(见上表) |
tasks | array | 任务快照,按定义顺序:{id, status, dependsOn, error?, result?} |
子任务产出聚合:落账成功任务的 result 字段携带 run() 返回值(原样, Int/String/Object 等任意 ScriptValue);返回 null 则字段省略(与未产出 同形);失败/超时/取消/跳过任务不携带。下游任务可在 run 内经 get_workflow 读取上游 result 组合数据流;嵌套工作流的产出也可借此在 父工作流快照逐层聚合(run 提交子工作流、等终局、返回其结果)。
v1 限制
- 工作流内并发由
maxParallel约束(默认 1 串行);跨工作流各自独立调度、互不设限。 - 条件
when只作分支过滤,不做循环/子工作流嵌套(子任务聚合为后续批次项)。 - 终局工作流驻留内存注册表直至进程退出,不自动清理。
- 本模块只负责脚本层本地执行;远程编排(Go server
WorkflowDetailDataDTO 对齐、子任务聚合)为后续批次项。