diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7bc848d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +.git +.gitignore +.DS_Store +bin +docs +sdk +examples +deploy +*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ef054ee --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +# syntax=docker/dockerfile:1.7 + +ARG TARGETOS +ARG TARGETARCH + +FROM golang:1.27.1-bookworm AS build + +ARG TARGETOS +ARG TARGETARCH +WORKDIR /src +ENV GOWORK=off + +COPY go.mod go.sum ./ +RUN go mod download +COPY . . + +RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -trimpath -ldflags='-s -w' -o /out/orbit ./cmd/orbit \ + && CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -trimpath -ldflags='-s -w' -o /out/orbit-migrate ./cmd/orbit-migrate \ + && CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -trimpath -ldflags='-s -w' -o /out/orbit-admin ./cmd/orbit-admin + +FROM scratch + +COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +COPY --from=build /out/orbit /usr/local/bin/orbit +COPY --from=build /out/orbit-migrate /usr/local/bin/orbit-migrate +COPY --from=build /out/orbit-admin /usr/local/bin/orbit-admin + +USER 65532:65532 +ENTRYPOINT ["/usr/local/bin/orbit"] diff --git a/Makefile b/Makefile index 25a0381..f5e0894 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ GO ?= go -.PHONY: fmt test vet build integration mysql-replication mysql-compatibility sdk-check protocol-check docs-check schedule-backlog +.PHONY: fmt test vet build image integration mysql-replication mysql-compatibility sdk-check protocol-check docs-check schedule-backlog fmt: $(GO) fmt ./... cd sdk/go && $(GO) fmt ./... @@ -26,6 +26,9 @@ build: cd examples/result-inbox && GOWORK=off $(GO) build -o ../../bin/orbit-inbox-example ./cmd/receiver cd examples/task-outbox && GOWORK=off $(GO) build -o ../../bin/orbit-outbox-example ./cmd/sender +image: + docker build --tag $${ORBIT_IMAGE:-orbit:dev} . + integration: ./scripts/test-mysql.sh diff --git a/README.md b/README.md index 5800e70..362f07e 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ make fmt make test make vet make build +make image make integration make protocol-check make docs-check @@ -97,6 +98,7 @@ SDK 独立发布门禁使用 `make sdk-check`,在 `GOWORK=off` 下检查完整 - [Go SDK 接入](docs/sdk/README.md) - [通用场景示例](docs/examples/README.md) - [运行与发布手册](docs/20-operations-runbook.md) +- [容器发布说明](docs/21-container-deployment.md) - [设计文档总览](docs/README.md) Git 远端:`https://git.yuntuo.hk/k2safe/orbit.git`。当前在本地开发分支推进,SDK 尚未发布版本。 diff --git a/docs/03-http-websocket-protocol.md b/docs/03-http-websocket-protocol.md index 5b800a9..d9706af 100644 --- a/docs/03-http-websocket-protocol.md +++ b/docs/03-http-websocket-protocol.md @@ -47,7 +47,7 @@ Weave以下接口已接入公共HTTP与SDK,具体字段和权限以[实例接 | `POST /v1/workflows/{workflow_id}/recovery/*` | 六类有证据恢复,按当前实例/步骤/任务版本核对 | | `GET /v1/workflows/{workflow_id}/operations` | 有界分页读取流程操作审计摘要,正文另用单条查询 | -流程列表和完整历史查询仍待交付;恢复必须带预期状态版本、稳定操作身份、原因与证据,不提供任意修改状态的通用入口。 +流程列表、实例筛选、激活/轮次/信号历史和状态事件时间线已交付;字段、权限和有界分页以[实例查询](api/workflow-queries.md)、[流程历史](api/workflow-history.md)和[事件时间线](api/workflow-events.md)为准。恢复必须带预期状态版本、稳定操作身份、原因与证据,不提供任意修改状态的通用入口。 暂停和继续使用独立管理权限、预期控制版本、幂等操作身份与原因;同一操作重报返回原确认,过期控制版本不能覆盖后来的操作。建议 `200` 确认门控已提交,后续执行进度通过查询观察;门控失效条件和终态操作错误在协议评审时固定。 diff --git a/docs/08-development-plan.md b/docs/08-development-plan.md index 708b1d6..64096fe 100644 --- a/docs/08-development-plan.md +++ b/docs/08-development-plan.md @@ -31,7 +31,7 @@ | P4 Weave 主流程 | SDK 定义构建与发布校验、实例、顺序/分支/结构化并行汇合、信号/定时等待、版本绑定 | 重启接续、早到/重复信号、并行竞争、内部事件重放、发布版本兼容;端到端通用流程 | 已完成平台功能阶段验收:[原功能及W01–W17逐项核对](reports/phase-4-5.md)、[版本/暂停/全停回归](reports/phase-4-5-races.md)、[提交故障边界](reports/phase-6-fault-boundaries.md)。研发发布、固定版本、顺序/分支/有限并行、信号/时间等待、公共API/SDK及可运行示例均已交付;生产拓扑与发布兼容继续P6/P7 | | P5 Weave 恢复与查询 | 有界查询、暂停继续、取消、人工核查恢复、控制门控与审计 | 轮次与尝试独立预算;暂停/开始/回执/超时竞争;恢复保留预算;未知结果不盲目重复 | 已完成平台功能阶段验收:[原功能核对](reports/phase-4-5.md)。有界查询、独立预算、暂停继续/取消、六类恢复、历史/筛选/事件/来源与SDK场景均已交付;真实竞争、COMMIT断线及进程全停保留原身份、截止和预算。运维、容量与首版发布继续P6/P7 | | P6 生产验证与运维 | 完整监控、凭据轮换、备份恢复、滚动升级、运行手册、可复现负载和故障工具 | 对照生产验收清单执行,报告环境/指标/遗留项;容量、RPO/RTO 按真实拓扑验证 | 进行中;已补[精确故障边界](reports/phase-6-fault-boundaries.md)和[进程观测](reports/phase-6-observability.md);继续业务积压/阶段延迟、凭据轮换及其余生产门槛 | -| P7 首版交付核对 | SDK 兼容与发布准备、完整 API 手册、场景示例、全量回归及交付清单 | 新接入者按文档跑通全部示例;所有首版能力可追溯到实现与测试;报告实际生产边界 | 进行中;已补[通用文件转换示例](reports/phase-7-file-conversion.md)、[SDK独立发布门禁](reports/phase-7-sdk-release.md)、[当前协议兼容矩阵](reports/phase-7-compatibility.md)、[历史任务 API 双向演练](reports/phase-7-historical-compatibility.md)、[当前回归状态](reports/phase-7-regression-status.md)和[首版交付核对清单](release-checklist.md),仍需带标签的完整跨版本矩阵、宿主机全量回归和目标拓扑验收 | +| P7 首版交付核对 | SDK 兼容与发布准备、完整 API 手册、场景示例、全量回归及交付清单 | 新接入者按文档跑通全部示例;所有首版能力可追溯到实现与测试;报告实际生产边界 | 进行中;已补[通用文件转换示例](reports/phase-7-file-conversion.md)、[SDK独立发布门禁](reports/phase-7-sdk-release.md)、[当前协议兼容矩阵](reports/phase-7-compatibility.md)、[历史任务 API 双向演练](reports/phase-7-historical-compatibility.md)、[当前回归状态](reports/phase-7-regression-status.md)、[首版交付核对清单](release-checklist.md)和[容器发布说明](21-container-deployment.md),镜像已完成 linux/amd64 构建验证;仍需带标签的完整跨版本矩阵和目标拓扑验收 | SDK、文档与示例随 P1–P5 同步开发,P7 是全量核对,不是最后才开始补文档。 diff --git a/docs/11-workflow-admission.md b/docs/11-workflow-admission.md index 993257e..5044f22 100644 --- a/docs/11-workflow-admission.md +++ b/docs/11-workflow-admission.md @@ -1,6 +1,6 @@ # Weave 实例受理与首批工作 -状态:实例Start/Get/Steps、单步详情、固定版本、首批事务及后台推进已实现,并已接入[公共HTTP与独立SDK](api/workflows.md)。控制、信号、人工恢复见[恢复API](api/workflow-recovery.md)。当前视图与操作审计可读,完整历史、实例列表和生产验收继续交付。 +状态:实例Start/Get/Steps、单步详情、固定版本、首批事务及后台推进已实现,并已接入[公共HTTP与独立SDK](api/workflows.md)。控制、信号、人工恢复见[恢复API](api/workflow-recovery.md)。当前视图、操作审计、实例列表、有界历史和事件时间线均已接入;生产验收继续按交付清单推进。 ## 1. 受理事务 @@ -49,14 +49,14 @@ Get返回当前实例视图;Start重报返回受理时冻结的原始视图, | 活跃实例 | 每个namespace最多10000个RUNNING/WAITING/CANCELLING/NEEDS_REVIEW实例;终态不计入;满额仍可恢复原受理回执 | | 信号关联 | 新受理最多512字节;数据库兼容旧191字符最长764字节,升级不截断历史 | | 截止 | 数据库时间生成;任务、查询与等待均不超过实例总截止 | -| 自动运行 | Inbox消费、根待续、TIMER到期及后续POLL轮次已接入;SIGNAL与最终查询竞争已接入,内部控制与结清已接入,内部核查及TASK恢复已接入,等待恢复已接入内部服务,公共API/SDK仍待实现 | +| 自动运行 | Inbox消费、根待续、TIMER到期及后续POLL轮次已接入;SIGNAL与最终查询竞争已接入,内部控制与结清已接入,内部核查及TASK恢复已接入,等待恢复已接入内部服务,公共HTTP/SDK、实例列表、历史查询和事件时间线均已接入 | 迁移000018为Wait增加signal_name和payload_version两个带中文注释的可空字段;NULL仅表示TIMER或尚未核实的历史元数据,未来消费者不得把历史NULL自动解释为有效的新信号等待。correlation_key转为精确字节存储;实例business_key改为utf8mb4_0900_bin。该迁移时为35个实体、含公共Record的295个直接持久化字段声明,全部有中文注释,继续保持零外键。 -## 5. 下一步接入 +## 5. 后续验收 -1. 结果消费与根待续运行器已按[运行器报告](reports/phase-4-runtime.md)验证;[定时和查询时钟](13-workflow-clock.md)已接入,继续补齐信号等待。 -2. 已有扫描核验暂停、截止与所属应用停用;继续信号/查询回执竞争及失败分支结清,恢复保留原截止和次数。 -3. 接通实例公共HTTP、独立SDK、来源查询和可运行端到端场景,同时实施真实节点退出与接管回归。 +1. 持续按[运行器报告](reports/phase-4-runtime.md)和全量回归验证结果消费、根待续、定时/查询时钟及信号等待。 +2. 在目标拓扑继续核验暂停、截止、应用停用、信号/查询回执竞争、失败结清和节点接管,恢复必须保留原截止和次数。 +3. 生产发布还需完成容量、复制切换、备份介质、RPO/RTO及正式兼容矩阵验收。 -本阶段验证见[实例受理回归记录](reports/phase-4-admission.md)。纯受理测试不是流程运行验收,P4–P7仍按[完整计划](08-development-plan.md)推进。 +本阶段历史验证见[实例受理回归记录](reports/phase-4-admission.md);当前端到端证据见[P4/P5核对](reports/phase-4-5.md)和[当前回归状态](reports/phase-7-regression-status.md)。功能回归不替代流程的生产拓扑和容量验收。 diff --git a/docs/21-container-deployment.md b/docs/21-container-deployment.md new file mode 100644 index 0000000..52be846 --- /dev/null +++ b/docs/21-container-deployment.md @@ -0,0 +1,64 @@ +# Orbit 容器发布说明 + +本文定义通用 Orbit 镜像的构建内容、启动契约和探针语义。镜像不包含业务 Worker、行业规则或数据库;数据库连接、凭据和 TLS 参数由部署环境注入。 + +## 1. 构建 + +根目录的 `Dockerfile` 使用仓库声明的 Go 1.27.1 构建三个可执行文件: + +- `/usr/local/bin/orbit`:HTTP、Worker/Event WebSocket 和后台恢复进程。 +- `/usr/local/bin/orbit-migrate`:显式执行迁移;服务启动不会自动改库。 +- `/usr/local/bin/orbit-admin`:结构核验、凭据初始化和只读运维命令。 + +构建阶段关闭 CGO 并使用 `-trimpath`,运行阶段为无 shell 的最小镜像,以减少运行时写入面。镜像保留系统 CA 证书,允许通过受保护 DSN 使用 MySQL TLS。 + +```sh +docker build --platform linux/amd64 -t registry.example/orbit:dev . +docker image inspect registry.example/orbit:dev --format '{{.Id}}' +``` + +生产发布应把标签绑定到不可变提交和镜像摘要,并在目标架构重新构建或执行等价的交叉构建核验。`registry.example` 只是占位符,不是平台依赖。 + +## 2. 迁移、核验和启动 + +迁移与服务使用同一镜像但分开执行;迁移账户和运行账户由数据库权限策略隔离。以下命令只展示容器契约,凭据必须来自秘密管理: + +```sh +export ORBIT_MYSQL_DSN='user:password@tcp(db.internal:3306)/orbit' + +docker run --rm \ + --env ORBIT_MYSQL_DSN \ + --entrypoint /usr/local/bin/orbit-migrate \ + registry.example/orbit:dev up + +docker run --rm \ + --env ORBIT_MYSQL_DSN \ + --entrypoint /usr/local/bin/orbit-admin \ + registry.example/orbit:dev verify + +docker run --rm \ + --env ORBIT_MYSQL_DSN \ + --env ORBIT_HTTP_ADDR=0.0.0.0:8080 \ + --env ORBIT_METRICS_ADDR=127.0.0.1:9090 \ + --publish 8080:8080 \ + registry.example/orbit:dev +``` + +生产编排应先完成迁移和 `verify`,再启动新节点。服务收到 `SIGTERM` 后停止接收新连接并在有限窗口内关闭 HTTP、WebSocket 和后台循环;编排器的终止宽限期必须覆盖该窗口。启动后才能把节点加入流量池。 + +## 3. 探针和监听边界 + +负载均衡或编排器使用: + +```text +GET /health/live 进程存活 +GET /health/ready MySQL、迁移账本及零外键检查 +``` + +`ready` 返回 `503` 时应摘除节点并保留原幂等键;不能把数据库连接失败解释为业务失败。metrics 监听由 `ORBIT_METRICS_ADDR` 单独启用,默认关闭,不应通过公共业务入口暴露。 + +镜像内没有 shell 和调试工具,故障定位依赖结构化日志、健康响应、受保护指标和 `orbit-admin observe snapshot`。不要在容器中执行迁移回滚、删除历史事件或修改审计数据。 + +## 4. 发布验收 + +镜像构建通过只证明发布物可复现,不等于生产高可用。发布候选仍需按[交付核对清单](release-checklist.md)完成真实 MySQL 回归、滚动替换、复制切换、容量、备份恢复和 RPO/RTO 验收。业务 Worker 继续独立部署,通过 HTTP/WebSocket SDK 接入。 diff --git a/docs/README.md b/docs/README.md index ff2d14d..14a762e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,6 +20,7 @@ | [19 容量模型](19-capacity-model.md) | 企业规模到任务、流程、数据库与连接负载的推导及生产验收方法 | | [P7 协议兼容矩阵](reports/phase-7-compatibility.md) | 当前协议门禁、历史提交双向任务 API 演练与正式标签矩阵边界 | | [20 运行与发布手册](20-operations-runbook.md) | 启动、发布、滚动停止、数据库恢复、备份和事故处理 | +| [21 容器发布说明](21-container-deployment.md) | 最小镜像、迁移/核验/启动顺序、探针和发布边界 | | [09 可靠结果订阅](09-result-subscription-core.md) | 提交水位、冻结结果与可靠交付 | | [10 Weave决策与交付](10-workflow-engine-core.md) | 有限步骤决策和内部结果Inbox | | [11 Weave实例受理](11-workflow-admission.md) | 固定版本、初始图和首批任务事务 |