Files
orbit/docs/api/workflows.md

174 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 流程实例、控制、信号与操作审计
状态:下表公共 HTTP 与独立 Go SDK 已接入。定义发布见[定义接口](workflow-definitions.md),人工恢复见[恢复接口](workflow-recovery.md),完整运行例子见[并行作业与回执](../examples/workflow.md)。SDK 尚未发布正式版本,服务端与 SDK 应使用同一开发版本。
实例筛选分页继续开发;[历史激活、轮次、信号和信号资源审计](workflow-history.md)已接入;[Pulse任务流程来源](task-source.md#5-流程固定来源)已接入。旧冻结回执可能不含新增的activation_sequence,应另读当前步骤详情;当前步骤详情只反映当前激活;旧记录保留在数据库,不能把本页的当前视图当作全部历史。
## 1. 路由、权限与 SDK
下文 `{id}` 为32位小写十六进制流程实例ID,不是定义ID;身份和命名空间来自凭据。所有读取均检查固定定义引用的全部队列。变更还需要 `Content-Type: application/json`、`Authorization: Bearer <token>` 和一个稳定的 `Idempotency-Key`;键最长128字节,字符规则沿用[任务协议](tasks.md)。请求体最大512 KiB,拒绝重复字段、大小写别名、未声明字段和多余查询参数。
| 方法与路径 | 权限 | Go SDK 方法 |
| --- | --- | --- |
| `POST /v1/workflows` | `workflows:start`;有任务队列时还需 `tasks:submit` | StartWorkflow |
| `GET /v1/workflows/{id}` | `workflows:read` | GetWorkflow |
| `GET /v1/workflows/{id}/steps` | `workflows:read` | GetWorkflowSteps |
| `GET /v1/workflows/{id}/steps/{key}` | `workflows:read` | GetWorkflowStep |
| `POST /v1/workflows/{id}/control` | `workflows:control` | ControlWorkflow |
| `POST /v1/workflows/{id}/signals` | `workflows:signal` | SendWorkflowSignal |
| `GET /v1/workflows/{id}/signals/{signal}` | `workflows:read` | GetWorkflowSignal |
| `GET /v1/workflows/{id}/operations` | `workflows:audit:read` | ListWorkflowOperations |
| `GET /v1/workflows/{id}/operations/{operation}` | `workflows:audit:read` | GetWorkflowOperation |
GET成功为200;启动及信号首次受理为201,原键回执为200;控制成功为200。控制响应表示意图已保存,取消结清由后台完成。SDK签名、独立类型及各字段中文说明见[调用方法](../../sdk/go/workflow_instances.go)和[协议类型](../../sdk/go/workflow_instance_types.go)。
CLI显式开关分别为:`--workflow-access`(定义读/发布)、`--workflow-run-access`(实例读/启动)、`--workflow-control-access`(实例读/控制)、`--workflow-signal-access`(实例读/信号)、`--workflow-recovery-access`(实例读/恢复)、`--workflow-audit-access`(流程操作审计读)。普通 Worker、定义发布及任务核查权限均不会自动获得流程管理权限。初始化会先验证权限集合再交付凭据,具体命令见[示例](../examples/workflow.md)。
## 2. 固定版本启动
`StartWorkflow(ctx, key, StartWorkflowRequest)` 的请求:
```json
{
"definition_id": "11111111111111111111111111111111",
"version": "v1",
"input": {"n": 9007199254740993},
"business_key": "operation-001 "
}
```
| 字段 | 类型与约束 |
| --- | --- |
| definition_id | 必填,当前命名空间的定义ID |
| version | 必填,1–64个ASCII版本字符,首字符字母或数字,之后还可用 `_ . -`;不解析latest |
| input | 必填,最多256 KiB JSON,必须符合固定版本输入契约;显式null与缺失不同,数字不经过float64 |
| business_key | 可选,默认空字符串,最多191个Unicode字符;尾部空格保留,不能替代幂等键 |
示意完整回执:
```json
{
"request_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"data": {
"instance": {
"id": "22222222222222222222222222222222",
"namespace_id": "33333333333333333333333333333333",
"definition_id": "11111111111111111111111111111111",
"definition_version_id": "44444444444444444444444444444444",
"version": "v1",
"state": "RUNNING",
"revision": "2",
"paused": false,
"control_revision": "1",
"input": {"n": 9007199254740993},
"business_key": "operation-001 ",
"deadline_at": "2026-09-18T08:01:00Z",
"created_at": "2026-09-18T08:00:00Z",
"updated_at": "2026-09-18T08:00:00Z"
},
"deduplicated": false
}
}
```
`GetWorkflow`的data直接是instance对象。可能状态为RUNNING、WAITING、CANCELLING、NEEDS_REVIEW、SUCCEEDED、FAILED、CANCELLED;paused是独立标记。`output`在存在结果时返回,成功输出可以为显式null。`cancel_requested_at`、`stop_kind`(CANCEL/FAILURE)、`stop_requested_at`、`completed_at`仅有值时返回。所有时间为UTC RFC3339,revision及control_revision为十进制字符串,SDK使用uint64。
启动固定定义版本和总截止,并在同事务创建门控、步骤和首批任务。原键同内容返回**首次受理快照**,不重算时间,不代表当前状态;同键不同内容返回IDEMPOTENCY_CONFLICT。网络响应丢失时保持原键和原请求核对,再用GetWorkflow读取当前状态。每命名空间最多10000个未终结实例,已保存的原回执在满额时仍可恢复。
## 3. 步骤及当前激活
GetWorkflowSteps返回 `{instance_id, revision, steps}`,steps按key排序、最多128项,不含内部根步骤。每项含 `id/key/kind/state/revision`;已激活时还含 `activation_id/activation_sequence`,TASK还含直接 `task_id`。未激活步骤没有激活ID和代次。步骤状态包括BLOCKED、ACTIVE、WAITING、SUCCEEDED、FAILED、CANCELLED、NEEDS_REVIEW、SKIPPED。
GetWorkflowStep返回单个步骤详情,实例revision与当前步骤同事务读取:
```json
{
"request_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"data": {
"instance_id": "22222222222222222222222222222222",
"revision": "8",
"step": {
"id": "55555555555555555555555555555555",
"key": "receipt",
"kind": "SIGNAL",
"state": "WAITING",
"revision": "2",
"activation_id": "66666666666666666666666666666666",
"activation_sequence": 1
},
"input": {"name": "done", "payload_version": "v1", "correlation": "operation-001 "},
"activated_at": "2026-09-18T08:00:05Z",
"wait": {
"id": "77777777777777777777777777777777",
"kind": "SIGNAL",
"state": "WAITING",
"name": "done",
"payload_version": "v1",
"correlation_key": "operation-001 ",
"deadline_at": "2026-09-18T08:00:35Z"
}
}
}
```
- `input/output`属于当前激活,每次只读取一份;未激活或尚无输出时省略,显式null保留。`activated_at/completed_at`属于当前激活,不能据新激活时间重算原预算。
- POLL的 `poll` 包含 used_rounds、first_round、first_round_attempts_used、max_rounds、max_attempts_per_round、interval_ms、deadline_at、last_task_id;current_task_id、next_poll_at、resolved_at在有值时返回。last_task_id指当前激活最后业务轮任务,可再通过GetTask读取其状态/版本。
- SIGNAL、TIMER和有最终信号的POLL返回 `wait`,包含当前等待身份、类型、状态、原截止和关联;name/payload_version不适用于TIMER,旧未核验等待也可能缺失。winner_signal_id和resolved_at在有值时返回。已选中赢家不代表在途任务已结清。
- 时间预算不会随人工换代增加。信号发送者应读取activation_sequence,不能把激活ID、步骤revision或任务尝试epoch当作等待代次。
## 4. 暂停、继续与取消
`ControlWorkflow(ctx, id, key, WorkflowControlRequest)`:
```json
{"operation":"PAUSE","expected_control_revision":"1","reason":"维护期间停止推进新工作"}
```
operation必填,为PAUSE/RESUME/CANCEL;expected_control_revision为读取到的非零control_revision字符串,reason为1–1024个Unicode字符,不允许全空白或NUL。成功data为 `{instance, deduplicated}`,instance字段同启动回执。新决定使用旧控制版本返回STATE_CONFLICT;原键恢复仍返回第一次的冻结决定。
PAUSE关闭新执行授权,在途结果继续收集;RESUME不清除NEEDS_REVIEW,不撤销首次停止目标,不延长原截止。CANCEL保存取消意图并停止后继,保留在途许可直到真实执行结束;未知效果仍进入核查。后台任务结果改变通用revision,不要求操作者追逐每个结果去更新control_revision。详细结清规则见[控制设计](../15-workflow-controls.md)。
## 5. 有身份的外部信号
`SendWorkflowSignal(ctx, id, key, SendWorkflowSignalRequest)`:
```json
{
"name":"done",
"payload_version":"v1",
"target_step_key":"receipt",
"target_activation_sequence":1,
"correlation_key":"operation-001 ",
"payload":{"n":9007199254740993},
"reason":"已核验外部回执",
"evidence_ref":"evidence:receipt-001"
}
```
name/payload_version/target_step_key必填,分别最多128/32/64个ASCII名称字符;代次为非零uint32数字。correlation_key为1–512字节UTF8、精确匹配并保留尾部空格。payload必填、最多256 KiB,符合固定契约时可显式null。reason规则同控制原因;evidence_ref可选、最多512个Unicode字符,不含空白或控制字符,平台不会访问这个引用。
成功data为 `{signal, deduplicated}`。signal字段:id、namespace_id、workflow_id、revision字符串、name、payload_version、target_step_key、target_activation_sequence、correlation_key、payload、actor_id、state、accepted_at、expires_at;evidence_ref、disposition、consumed_wait_id在有值时返回。actor_id从认证获得。GetWorkflowSignal直接返回当前signal对象。
受理与消费分离:PENDING可以稍后变为CONSUMED、REJECTED或EXPIRED。每实例全部历史受理记录最多1024条,原键回执先于上限检查。早到信号可以指定首次代次1;当前旧代次信号保存为REJECTED/STALE_ACTIVATION,未来代次冲突。恢复为新代次后,原信号原键仍返回旧回执,不能用重报改变目标。最终查询与信号按原事件时间竞争,PENDING查询不争夺业务完成权,见[信号设计](../14-workflow-signals.md)。
## 6. 操作审计与错误处理
ListWorkflowOperations接受HistoryPageRequest:limit默认20、范围1–100;cursor最大1024字节,绑定命名空间、流程ID和查询种类,不可跨资源复用。data为 `{items, next_cursor?}`;每项含 id、workflow_id、operation_id、actor_id、action、created_at,按时间及ID倒序。GetWorkflowOperation除这些字段外还返回reason、evidence_ref(可空省略)、before、after JSON摘要。单独读取正文,避免列表聚合大结果。
该接口当前查询resource_kind=workflow的启动、推进、控制和恢复审计;独立任务核查审计通过恢复回执的task_audit_id关联。信号自身的受理状态通过GetWorkflowSignal读取;[信号资源审计及历史激活查询](workflow-history.md)使用独立路由,统一状态事件时间线仍待核对交付。
| HTTP/错误码 | 处理方式 |
| --- | --- |
| 400 INVALID_ARGUMENT | 修正字段、固定契约或查询游标;不要把遗漏声明默认成true |
| 401 UNAUTHENTICATED / 403 PERMISSION_DENIED | 核对凭据和显式动作权限,重报不会绕过撤权 |
| 404 NOT_FOUND | 资源不存在、跨命名空间或队列不在授权范围 |
| 409 STATE_CONFLICT / IDEMPOTENCY_CONFLICT | 当前状态/版本不符或原键请求改变;先读取权威状态 |
| 409 WORKFLOW_INSTANCE_LIMIT / WORKFLOW_SIGNAL_LIMIT | 固定资源数量上限,不能通过新键盲目补发 |
| 429 QUEUE_FULL / APPLICATION_FULL | 新工作配额不足;保持原请求身份核对,服务端给Retry-After |
| 413 BODY_TOO_LARGE / 415 UNSUPPORTED_MEDIA_TYPE | 缩小请求或使用application/json |
| 503 UNAVAILABLE / 网络异常 | 提交结果可能不明,保持原键和原命令核对;SDK不自动换键 |
已实现路由之外的路径为404。回归证据和剩余交付范围见[公共接入报告](../reports/phase-5-public-api.md)。
实例集合读取 `GET /v1/workflows` 已接入筛选分页,参数、权限及SDK见[查询手册](workflow-queries.md)。