# Orbit · 星轨 **Go + MySQL 构建的任务调度与流程编排平台。** 业务应用通过 HTTP 提交任务,Worker 通过 WebSocket 执行,结果通过可靠订阅交付;任务状态、计划、流程检查点与审计保存在 MySQL。 - **Pulse · 脉动**:异步任务、延迟执行、定时计划、执行授权、重试与结果订阅。 - **Weave · 织流**:研发定义并发布流程,支持顺序、并行、条件分支、等待信号、有界查询和人工恢复。 - **Console**:账号密码登录的管理工作台,按应用与环境查看运行快照;支持任务/流程筛选、资源分页、ID 定位、审计与接入配置复制。[控制台使用说明](docs/console.md)。 主分支:`main`。当前版本:**`v0.1.2`**。源码、SDK 和 Outbox 适配包采用固定版本发布,已发布标签不覆盖。变更见 [CHANGELOG](CHANGELOG.md)。 ## 从这里开始 | 你要做什么 | 入口 | | --- | --- | | 第一次启动平台、设置管理员 | [快速开始](#快速开始) | | 使用 Docker 启动,后续接入域名 | [Docker 与域名部署](#docker-与域名部署) | | 了解全部能力和用法 | [功能一览](#功能一览) | | 业务 Go 项目接入 | [SDK 怎么调用](#sdk-怎么调用) | | 直接运行完整场景 | [examples:28 个可运行示例](examples/README.md) | | 嵌入现有 HTTP 服务 | [HTTP + Outbox + Worker + Inbox](examples/http-service/README.md) | | 查字段、错误码、权限及协议 | [HTTP / WebSocket API](docs/api/README.md)、[Go SDK 手册](docs/sdk/README.md) | | 配置、排障、备份、发布 | [配置与运维](#配置与运维)、[运行手册](docs/20-operations-runbook.md) | ## 功能一览 每个示例目录都有 README、源码、启动方式和结果核对。接口手册包含字段、权限、错误码和恢复约定。 ### Pulse:任务与调度 | 功能 | 做什么 / 怎么用 | 可运行示例 / 接口 | | --- | --- | --- | | 即时任务与提交幂等 | `SubmitTask` 提交固定处理器版本与 JSON;重报复用原操作键,`GetTask` 查当前状态 | [tasks](examples/tasks/README.md) · [任务接口](docs/api/tasks.md) | | 延迟任务 | `DelayMS` 从首次受理计时;`AvailableAt` 指定绝对时刻 | [delayed-task](examples/delayed-task/README.md) | | 批量受理 | `SubmitTasks` 最多 32 项,逐项返回受理/拒绝/未知,按原身份补交 | [batch](examples/batch/README.md) · [批量接口](docs/api/batch-tasks.md) | | 自动 Worker | 注册处理器与版本,`NewWorker(...).Run(ctx)` 负责连接、授权、续租、上报与排空 | [worker](examples/worker/README.md) · [运行器手册](docs/sdk/worker-runtime.md) | | 安全重试 | 冻结次数、退避与总时限;明确可重试失败自动再执行,未知效果按安全策略核查 | [retry](examples/retry/README.md) · [重试策略](docs/api/retries.md) | | 取消 | `CancelTask` 保存取消意图;运行中的处理器配合停止并结清 | [cancellation](examples/cancellation/README.md) | | 定时计划 | Cron / 固定间隔、时区、不可变版本、漏跑策略、暂停/恢复和触发历史 | [schedules](examples/schedules/README.md) · [计划接口](docs/api/schedules.md) | | 资源退役 | 结清后退役订阅与队列,释放订阅名额,保留历史和审计 | [运行示例](sdk/go/examples/resource-lifecycle/README.md) · [接口与规则](docs/api/resource-retirement.md) | | 队列资源控制 | 创建/配置队列并发、开始速率、积压上限和暂停;满额返回背压 | [resources](examples/resources/README.md) · [队列接口](docs/api/queues.md) | | 应用共享配额 | 同一应用的多个命名空间/队列共享总额度 | [application-resources](examples/application-resources/README.md) | | 资源键互斥 | `ConcurrencyKey` 协调跨队列同资源任务,资源端核验递增许可序号 | [keyed-concurrency](examples/keyed-concurrency/README.md) | | 优先级 | 任务优先级 0–9,结合等待时间排序与节点轮转派发 | [priority](examples/priority/README.md) | | 查询与来源 | 按队列、状态、业务键、创建时间分页;追溯普通提交、计划、流程和人工重试来源 | [task-query](examples/task-query/README.md) · [来源接口](docs/api/task-source.md) | | 历史与证据 | 查询每次尝试、原结果及迟到/冲突报告,保留原始记录 | [history](examples/history/README.md) | | 人工核查与重试 | `ReviewTask` 提交证据;`RetryTask` 创建关联新任务并保留审计 | [recovery](examples/recovery/README.md) | ### Weave:流程编排 | 功能 | 做什么 / 怎么用 | 可运行示例 / 接口 | | --- | --- | --- | | 定义与版本 | 研发使用 SDK 创建定义、发布不可变版本;运行实例固定启动版本 | [workflow-definition](examples/workflow-definition/README.md) · [定义格式](docs/api/workflow-definition-format.md) | | 顺序、条件、并行与汇合 | 用有限结构组合任务与结果映射;持久化每一步和推进检查点 | [workflow](examples/workflow/README.md) · [实例接口](docs/api/workflows.md) | | 时间与外部信号等待 | TIMER 到期继续;SIGNAL 按固定等待身份接收外部回执 | [workflow](examples/workflow/README.md) · [信号设计](docs/14-workflow-signals.md) | | 有界重复查询 | POLL 分别限制业务查询轮次和单轮请求重试,处理中继续等待,耗尽转核查 | [workflow-poll](examples/workflow-poll/README.md) | | 暂停、继续、取消 | 停止推进后续工作,同时收集已发出的在途结果 | [控制接口](docs/api/workflows.md) · [控制语义](docs/15-workflow-controls.md) | | 人工恢复 | 按原因、证据、版本核查任务/步骤/等待;恢复沿用原历史、预算和截止 | [workflow-recovery](examples/workflow-recovery/README.md) · [恢复接口](docs/api/workflow-recovery.md) | | 实例查询与审计 | 筛选分页,查步骤详情、历史激活、查询轮次、信号及状态时间线 | [workflow-query](examples/workflow-query/README.md) · [历史接口](docs/api/workflow-history.md) · [时间线](docs/api/workflow-events.md) | ### 业务接入与管理 | 功能 | 做什么 / 怎么用 | 入口 | | --- | --- | --- | | 可靠结果订阅 | 先创建订阅,再由 EventConsumer 通过 WebSocket 接收结果;业务提交后 ACK,失败按预算重新交付 | [subscriptions](examples/subscriptions/README.md) · [消费 SDK](docs/sdk/event-consumer.md) | | 事务 Outbox 公共包 | `EnqueueTx` 将待发请求写入业务事务,`Run` 后台发送;网络结果不明复用原身份 | [MySQL 适配包](docs/sdk/outbox-mysql.md) · [task-outbox](examples/task-outbox/README.md) | | 业务结果 Inbox | 事件去重与业务更新同事务,提交成功后确认交付 | [result-inbox](examples/result-inbox/README.md) | | HTTP 服务完整生命周期 | 业务接口、Outbox、Worker、结果消费、就绪检查和有界关闭放进同一业务服务 | [http-service](examples/http-service/README.md) | | 平台身份与凭据 | 应用/命名空间/队列授权范围、凭据轮换/撤销;SDK 不直连平台数据库 | [鉴权](docs/api/authentication.md) · [凭据管理](docs/api/authentication.md) | | 账号密码控制台 | 初始化管理员,按应用/环境/队列查看任务、计划、流程、交付与归档,列表和详情显示应用归属 | [Console 手册](docs/console.md) · [应用范围](docs/api/console-scope.md) | | 保留策略与周期归档 | 配置各类数据保留天数,持久化归档计划/作业,分页、续跑、重试与文件核验 | [保留策略](docs/api/retention.md) · [周期归档](docs/api/archive-scheduler.md) | | 运维与观测 | 健康/readiness、独立指标端口、迁移核验、负载工具、备份恢复与故障演练 | [观测](docs/api/observability.md) · [运维](docs/20-operations-runbook.md) | ## 快速开始 需要 **Go 1.27.1、MySQL 8.4**,先创建专用数据库 `orbit`;下方管理员密码提示和读取队列 ID 的辅助命令使用 Python 3。程序通过环境变量配置,**不会自动读取 `.env`**。如当前 shell 设置了 `GOTOOLCHAIN=local`,必须安装满足版本要求的 Go。 ### 1. 获取代码并迁移数据库 ```sh git clone --branch v0.1.2 https://git.yuntuo.hk/k2safe/orbit.git cd orbit export ORBIT_MYSQL_DSN='user:password@tcp(127.0.0.1:3306)/orbit' export ORBIT_HTTP_ADDR='127.0.0.1:8080' go run ./cmd/orbit-migrate up ``` DSN 替换为实际账号密码。`--branch v0.1.2` 检出固定发布版本;参与开发使用 `git switch main`。已有库先备份,再按[升级与发布手册](docs/20-operations-runbook.md)停旧写节点、迁移和核验;不修改已应用的迁移文件。 ### 2. 一次性创建示例资源与管理员 下面在独立演示应用中授予所有流程及任务演示所需权限,并设置一个管理员。密码至少 12 字节,通过标准输入传递,不写入命令行或 Git。 ```sh umask 077 mkdir -p .local python3 -c 'import getpass; print(getpass.getpass("设置管理员密码(至少12字节):"))' | \ go run ./cmd/orbit-admin bootstrap \ --application sample-app --namespace default --environment development \ --queue examples --worker-access --schedule-access --event-access \ --recovery-access --workflow-access --workflow-run-access \ --workflow-control-access --workflow-signal-access \ --workflow-recovery-access --workflow-audit-access \ --console-username admin --console-display-name 'Orbit 管理员' \ --console-password-stdin --output .local/development.credentials.json ``` 管理员可在「应用接入」页面新建应用和初始队列、查看和调整有效期、平滑换证(默认长期 Token,换证时新旧共存 7 天),随时查看、复制包含当前 Token 的完整接入配置,或下载 orbit.env。设置 `ORBIT_CONSOLE_APPLICATION_ADMIN=admin` 指定唯一接入管理员,并通过 `ORBIT_CREDENTIAL_KEY_FILE` 配置 Token 加密保管密钥;本地 Compose 自动生成并持久保存。[应用接入使用与接口文档](docs/api/console-applications.md)。 初始化只运行一次,后续重启复用数据库、账号和 SDK 凭据。凭据 JSON 是服务端程序访问 API 的秘密文件,**控制台不需要选择或上传它**。已有资源增加管理员的方法见 [Console 手册](docs/console.md);真实接入按实际角色缩小权限。 ### 3. 启动平台,进入控制台 ```sh export ORBIT_CONSOLE_QUEUE_ID="$(python3 -c 'import json; print(json.load(open(".local/development.credentials.json"))["queue_id"])')" go run ./cmd/orbit ``` 打开 ****,用 `admin` 和刚设置的密码登录。页面自动使用当前访问地址请求服务端,统计与列表从平台接口读取 MySQL 中的数据。 ### 4. 跑一条完整执行链 另开终端,从仓库根目录执行: ```sh export ORBIT_URL=http://127.0.0.1:8080 export ORBIT_CREDENTIALS_FILE="$PWD/.local/development.credentials.json" cd examples go run ./health go run ./worker ``` 健康检查显示 `liveness=alive readiness=ready`;Worker 示例实际创建并执行三条文本任务,最后输出: ```text task=<任务ID> state=SUCCEEDED result={"text":"HELLO ORBIT"} task=<任务ID> state=SUCCEEDED result={"text":"REUSABLE WORKER"} task=<任务ID> state=SUCCEEDED result={"text":"DURABLE RESULT"} worker_drained=true started=3 confirmed=3 running=0 ``` 刷新控制台可查看这些任务。继续在 `examples` 目录运行 `go run ./schedules`、`go run ./workflow` 或 `go run ./workflow-poll` 体验定时和流程;全部 27 个场景及特殊准备条件见 [examples/README.md](examples/README.md)。 ## SDK 怎么调用 ### 安装固定版本 在自己的业务项目中执行: ```sh go get git.yuntuo.hk/k2safe/orbit/sdk/go@v0.1.2 # 业务事务需要 MySQL Outbox 时再安装: go get git.yuntuo.hk/k2safe/orbit/adapters/outbox/mysql@v0.1.1 ``` 无需本地源码或 `replace`。SDK 是独立 Go module,只依赖标准库和 WebSocket 客户端;MySQL 驱动属于可选适配包。子模块的 Git 标签分别为 `sdk/go/v0.1.2` 和 `adapters/outbox/mysql/v0.1.1`。 ### 提交、执行、接收结果 一次完整接入分为三个角色,可以分进程,也可以嵌入同一业务 HTTP 服务: ```text 业务事务 → Outbox → HTTP 提交到 Orbit → WebSocket Worker 执行业务 ↓ 业务数据 ← Inbox ← WebSocket 结果订阅 ← 持久化结果 ``` 下面是业务函数中的提交片段;完整 imports、main、Worker 注册和收尾见 [worker/main.go](examples/worker/main.go)。`baseURL` 为实际平台地址,例如 `https://orbit.example.com`;`token` 和 `queueID` 从业务配置/Secret 注入。 ```go client, err := orbit.NewClient(baseURL, orbit.Options{Token: token}) if err != nil { return err } // operationKey 和完整 request 必须先保存在业务库;网络重报仍使用原值。 request := orbit.SubmitTaskRequest{ QueueID: queueID, Handler: "object.prepare", HandlerVersion: "v1", PayloadVersion: "v1", Payload: json.RawMessage(`{"object_ref":"objects/input"}`), TaskTimeoutMS: 60000, Retry: orbit.RetryPolicy{MaxAttempts: 1, AttemptTimeoutMS: 10000}, RecoverySafety: orbit.RecoveryReconcileOnly, } accepted, err := client.SubmitTask(ctx, operationKey, request) if err != nil { return err } current, err := client.GetTask(ctx, accepted.Task.ID) if err != nil { return err } fmt.Println(current.ID, current.State) ``` 导入路径为 `orbit "git.yuntuo.hk/k2safe/orbit/sdk/go"`。处理器的名称、处理器版本和载荷版本必须与 Worker 注册能力一致;没有匹配的在线 Worker 时,提交成功也不会立即执行。 **任务受理不等于执行成功。** 同键重报返回原回执,最新状态用 `GetTask` 或结果事件核对。平台不能替外部系统保证“恰好执行一次”;副作用须使用业务幂等键、事务或证据核查。 结果通知使用 `NewEventConsumer(...).Run(ctx)`。先创建持久订阅,再提交希望接收的任务;消费函数在 Inbox 与业务变更明确提交后返回 nil,SDK 才 ACK。断线重连、重复交付和业务去重见[消费手册](docs/sdk/event-consumer.md)。 ### 现有 HTTP 服务如何接入 直接从 [examples/http-service](examples/http-service/README.md) 开始,完整命令、配置及 curl 请求见[运行手册](docs/examples/http-service.md)。该工程提供: 1. `init`:在独立业务库创建 Outbox、业务表、Inbox 和结果视图。 2. `provision`:创建可靠结果订阅,将订阅 ID 保存到部署配置。 3. `serve`:启动业务 HTTP、Outbox 发送器、Worker 和结果消费者。 4. 业务请求返回本地受理状态;随后查询到平台 TaskID、执行结果和业务视图。 5. 收到退出信号后,依次收尾 HTTP、发送器/Worker、结果消费者,最后关闭数据库。 只抽取发送器时使用[公共 Outbox 包](adapters/outbox/mysql/README.md):`EnqueueTx` 加入调用方事务,不提交事务、不发网络请求;`Run` 在后台提交并核对平台回执。业务确认钩子与 Outbox 确认同事务执行。 ## Docker 与域名部署 本机给其他服务联调,可直接运行 `./scripts/orbit-local.py up`,自动部署到 `18080`,生成管理员和 SDK 配置;完整地址、Docker 网络与启停方法见[本地 Compose 测试环境](deploy/local/README.md)。 仓库提供 [Dockerfile](Dockerfile)、[Compose 启动链](deploy/docker-compose.yml)和 [Nginx 配置](deploy/nginx/orbit.conf.example)。按[完整 Compose 手册](docs/22-compose-deployment.md)注入数据库密码、构建镜像、启动 MySQL/迁移/核验、初始化管理员,最后启动 Orbit。手册也包括停止、更新与两节点覆盖配置。 - Console 同源访问:域名反向代理到 Orbit 后,页面自动使用这个域名,无需在界面填写服务地址。 - 业务 SDK:把自己的 `baseURL` / 示例 `ORBIT_URL` 配置为该 HTTPS 域名,SDK 使用相应 WSS 地址。 - 网关保留 WebSocket Upgrade/Connection 头,健康检查使用 `/health/ready`。 - 停止容器保留 MySQL 和归档持久卷;更换镜像不等于删除数据。 ## 配置与运维 配置完整示例见 [.env.example](.env.example)。由 shell、部署平台或 Secret 管理器显式注入: | 配置 | 用途 | | --- | --- | | `ORBIT_MYSQL_DSN` | 平台数据库连接,迁移账号与运行账号按部署手册分开 | | `ORBIT_HTTP_ADDR` | 服务进程监听地址,例 `127.0.0.1:8080` | | `ORBIT_CONSOLE_QUEUE_ID` | 控制台默认队列;不授予账号额外权限 | | `ORBIT_CONSOLE_APPLICATION_ADMIN` | 指定唯一可接入和管理各应用的控制台登录名;空值不开放跨应用权限,多节点保持一致 | | `ORBIT_DB_MAX_OPEN` / `ORBIT_DB_MAX_IDLE` | 数据库连接池上限 | | `ORBIT_SHUTDOWN_TIMEOUT` | SIGTERM 关闭窗口,默认 10s | | `ORBIT_WORKFLOW_TICK_INTERVAL` / `ORBIT_SCHEDULE_TICK_INTERVAL` | 流程/计划后台扫描间隔,默认 1s | | `ORBIT_RECOVERY_TICK_INTERVAL` / `ORBIT_RUNTIME_BATCH_LIMIT` | 恢复扫描间隔与每批上限,默认 2s / 100 | | `ORBIT_WORKER_CONNECTION_LIMIT` / `ORBIT_EVENT_CONNECTION_LIMIT` | 每节点 WS 连接上限,默认各 128 | | `ORBIT_DISPATCH_WORKERS` / `ORBIT_DISPATCH_CAPACITY` | 派发并发和有界内存队列,默认 4 / 128 | | `ORBIT_METRICS_ADDR` | 独立内部指标监听,默认关闭 | | `ORBIT_RETENTION_*_DAYS` | 首次初始化保留窗口;控制台保存后以数据库策略为准 | | `ORBIT_ARCHIVE_ROOT` / `ORBIT_ARCHIVE_STORAGE_ID` | 周期归档卷路径与固定卷身份,二者一起配置 | | `ORBIT_ARCHIVE_MAX_BYTES` / `ORBIT_ARCHIVE_TICK_INTERVAL` | 归档卷预算和调度间隔,默认 10 GiB / 10s | 默认保留窗口:任务、流程、事件各 **365 天**,交付、Inbox、幂等记录各 **90 天**,审计 **2555 天**。控制台可修改策略并配置周期归档;未结清任务、未知效果、未确认交付等受保护记录不会按时间简单处理。**当前归档导出并保留源数据,尚未提供源数据自动删除执行器。** 详细规则见[保留策略](docs/api/retention.md)和[归档作业](docs/api/archive-scheduler.md)。 常用检查: ```sh curl --fail http://127.0.0.1:8080/health/ready go run ./cmd/orbit-admin verify go run ./cmd/orbit-admin observe snapshot ``` 数据库禁止外键和级联删除;关联一致性由事务校验,保留唯一约束、索引和 CHECK。持久化模型及 SQL 字段都有中文注释。已有迁移不可回改,演进采用前向迁移。 ## 项目目录 ```text cmd/ 平台、数据库迁移和管理命令 platform/ 应用、身份、授权、幂等、事件、审计 pulse/ 任务、Worker、重试、队列、定时计划 weave/ 流程定义、实例、步骤、等待和恢复 model/ 公共持久化类型与校验 internal/ MySQL 存储、HTTP/WS、配置与观测 sdk/go/ 可独立引用的 Go SDK adapters/outbox/mysql/ 可独立引用的 MySQL Outbox 包 examples/ 27 个可运行场景及各自 README deploy/ Compose、Nginx 和部署配置 scripts/ 构建、回归、故障和发布核验 docs/ API、SDK、场景、设计及验收报告 ``` ## 测试、版本与边界 在仓库根目录执行: ```sh make test vet build # 7 个模块的竞态测试、静态检查与构建 make sdk-check protocol-check docs-check make integration # 临时 MySQL、真实平台、示例及故障回归 make console-check # 前端查询状态回归(开发机需 Node.js) make console-e2e # 控制台端到端回归 ``` 集成测试需要 Docker、Python 3 和 OpenSSL 等工具,由脚本创建独立临时数据库并清理自建容器。生产容量与故障域验收另见[交付清单](docs/release-checklist.md);有限样本不能代表百万企业规模的生产容量。 `v0.1.2` 新增通用资源退役;此前已包含账号密码控制台、归档策略/周期作业、Outbox 公共包、HTTP 生命周期示例及统一示例目录;与上一版本的升级说明和验证结果见 [CHANGELOG](CHANGELOG.md) 与 [本次验证](docs/reports/resource-retirement.md)。当前未提供源数据删除、其他数据库 Outbox 适配,也不把单机或隔离环境多节点测试等同于生产跨故障域高可用验收。 更多资料:[设计文档](docs/README.md) · [持续开发计划](docs/08-development-plan.md) · [接口目录](docs/api/README.md) · [示例目录](examples/README.md) · [发布规则](docs/sdk/release.md)。