# 快速 Demo 核心契约 V1 冻结日期:2026-07-27 状态:`frozen-target` ## 1. 契约边界 Demo 公共 HTTP API 由两部分共同组成: 1. `openapi/platform-api-v1.yaml`:已经运行的脚本、稳定版本详情、数据资源和文件编辑锁接口。 2. `openapi/demo-core-extension-v1.yaml`:第 15 小步冻结、后续小步实现的上下文、Jupyter 票据、稳定版本列表、调度和运行查询接口。 内部 Storage 与 Runtime 接口继续分别以 `openapi/storage-api-internal-v1.yaml` 和 `openapi/runtime-api-internal-v1.yaml` 为准。 ## 2. 不可变约束 - 主标识使用 ULID;调度节点只引用不可变的 `versions_id`。 - 当前认证上下文由 `X-User-ID`、`X-Workspace-ID` 提供;以后换成 JWT 时不得改变业务 DTO。 - 修改调度方案必须提交 `workflow_version`,冲突返回 `412`。 - 创建调度、立即运行、启停和取消使用 `Idempotency-Key`。 - `schedule_runs.schedule_snapshot` 固化本次执行 DAG,后续编辑不影响已创建的运行。 - 浏览器不能拿到 Jupyter 内部 Token,只能获得短期访问 Cookie。 ## 3. 状态值 - 调度运行:`queued / running / succeeded / failed / cancelled / timed_out` - 节点运行:`queued / running / succeeded / failed / skipped / cancelled / timed_out` - 失败策略:`stop / continue` - 触发类型:`manual / cron / api / retry` ## 4. Redis Streams 路由 | Stream | Consumer Group | 事件 | 生产者 | 消费者 | |---|---|---|---|---| | `stream:scheduler:commands` | `schedule-orchestrator` | `schedule.run.requested` | Platform API / Cron Dispatcher | Schedule Orchestrator | | `stream:jobs:execute` | `job-workers` | `job.node.execute` | Schedule Orchestrator | Job Worker | | `stream:jobs:results` | `schedule-results` | `job.node.finished` | Job Worker | Schedule Orchestrator | 交付语义为至少一次。业务事务先写 `outbox_events`,发布成功后更新 Outbox;消费者处理前以 `consumer_inbox` 去重,业务更新与 Inbox 写入同一 MySQL 事务。只有业务事务提交成功后才确认 Redis 消息。 ## 5. 模块所有权 | 模块 | 拥有的数据与职责 | |---|---| | Platform API | 脚本、稳定版本、调度定义、运行查询、Outbox 写入 | | Runtime Manager | Workspace/Jupyter 生命周期与内部运行态 | | Nginx | 统一入口、Jupyter HTTP/WebSocket 代理 | | Schedule Orchestrator | 消费调度请求、解析 DAG、推进节点状态 | | Job Worker | 读取稳定版本、执行节点、保存日志/结果、报告终态 | | Storage Service | RustFS 对象元数据与预签名访问 | 模块间不得复制定义 DTO、状态枚举、错误结构或事件字段;契约变更必须先 升级本目录中的版本化文件。