Files
orders/README.md

157 lines
8.2 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.

# COOL SaaS 模块微服务起始项目
这是一个可复制到 `cool-midway-biz/microservices/<service-name>` 的干净起始项目。
它只包含托管 SaaS 模块微服务运行所需的基础结构,不包含 Demo 商品业务、Pilot、
Examples、测试 Fixture 或任何既有模块的生成契约。
## 初始化
1. 将本目录的项目文件复制到 `cool-midway-biz/microservices/<service-name>`,不要复制模板
仓库自身的 `.git`scaffold 工具也必须移除模板 origin再由业务项目重新初始化。
2. 修改 `package.json` 中的包名,并按需修改
`src/config/app.default.ts` 中的本地默认端口 `7101`
3. 在开发环境的模块管理页输入基础版本(例如 `1.0.0`)并锁定 Candidate平台会分配
Build Revision、`1.0.0-rc.<revision>` 候选版本和同名 release 分支。
4. 安装依赖后,用平台给出的精确 Revision 生成并启动开发实例:
```powershell
pnpm install
pnpm exec cool saas-model generate --module <module-code> --revision <build-revision>
pnpm dev
```
首次生成会初始化 Git如果需要、要求配置 `origin`,并切换到平台指定的
`release/<candidate-version>` 分支。CLI 会在项目根目录写入可提交的
`.cool-saas-candidate.json`其中只有模块、Revision、版本、分支与 checksum不包含
控制面 token、Runtime ticket 或其他 Secret。
`src/config/app.default.ts` 会直接导入 `src/saas/generated`。因此全新模板在首次生成
完成前不能编译,这是为了避免用占位契约冒充平台锁定的 Build Revision。
`start:local` 会显式开启仅限 `local/test` 的 Runtime bootstrap fallback本地控制面
启动命令也必须开启同一个 flag。两端未另设 token 时只使用仓库内公开的开发常量,
生产环境始终拒绝这条路径。
## CLI 生命周期
在微服务根目录执行:
```powershell
pnpm exec cool saas-model generate `
--module <module-code> `
--revision <build-revision>
pnpm build
```
管理端的“生成到本地”仍只负责选择目录并写入生成文件,不会初始化 Git、修改 remote
或切换分支;完整 Candidate 开发流程应使用上面的 CLI generate 命令建立这些 Git
约束。
使用默认输出目录时CLI 会写入 `src/saas/generated/<module-code>`,并自动维护
`src/saas/generated/index.ts` 稳定导出入口。
生成后可随时执行 `pnpm exec cool saas-model verify` 检查当前分支、候选锁、生成文件与
控制面的精确 Candidate 是否一致。`pnpm dev` 会先执行同一校验,再调用
`package.json` 中 `coolSaas.lifecycle.dev` 的非递归命令构建并启动原有开发宿主;因此
配置里不要写回 `pnpm dev`。项目接入自己的 watch/reload 工具后,可将该命令替换为对应
的开发启动命令。
CLI 生成的 `models.ts`、`contracts.ts`、`saas-actions.ts`、`saas-events.ts`、
`module.ts`、`index.ts` 和锁文件属于同一个不可变 Build请整体保留且不要手工修改。
## 固化 Candidate
开发联调完成后,先提交并将当前 release 分支推送到 `origin`,然后执行:
```powershell
pnpm run publish
```
该脚本只调用 `cool saas-model finalize`。CLI 从 `package.json` 的 `coolSaas.lifecycle`
读取并依次执行 `test` 与 `build`(本模板分别为 typecheck 和原有 build确认工作区仍然
干净且当前提交已推送后,创建并推送 `v<candidate-version>` Tag最后向控制面幂等提交
freeze 证据。生命周期子命令不得调用 `pnpm dev`、`pnpm publish` 或再次调用
`cool saas-model dev/finalize`,以免递归。
freeze 成功后,原来的 development 实例会因身份不再匹配而停止参与路由。再次执行
`pnpm dev`CLI 会读取候选的 Frozen Artifact只允许从完全一致且干净的 Git commit
以 `runtimeMode=frozen` 启动。请用这个固化实例完成最终验收;验收通过后才能在管理端
晋升 Stable。`accepted` 状态也可以用同一命令重启精确固化实例,但已晋升、拒绝、替代
或放弃的候选会被拒绝。
控制面地址与凭证继续使用 `COOL_SAAS_CONTROL_PLANE_URL`、`COOL_SAAS_TOKEN`,或 CLI 的
`--endpoint`、`--token` 参数。CLI token 只用于校验/freeze 请求,不会写入候选锁,也
不会传给测试、构建或开发宿主子进程。freeze 调用
`/internal/saas/module_release/freeze`,只发送 Bearer 凭证,不依赖浏览器 Cookie。
## 依赖与发布
`@cool-midway/core`、`@cool-midway/module-runtime` 和 `@cool-midway/rpc` 使用
`https://npm.blendercg.art/` 中已发布的精确版本。安装前通过环境变量提供私服凭证,
不要把 token 写入仓库:
```powershell
$env:NODE_AUTH_TOKEN='<registry-token>'
pnpm install
```
本地环境可以使用 Runtime 提供的开发配置。应用开发者在部署描述中只需要关注:
```ini
PORT=7101
SAAS_CONTROL_PLANE_URL=https://control-plane.example.com
```
`PORT` 是进程在容器内监听的健康检查端口,不是 Action RPC 的入口。同一镜像的所有
副本都可以监听 `7101`。宿主机可分别映射为 `17101:7101`、`17102:7101`,也可以完全
不发布端口;无论选择哪种方式,容器内配置都保持不变。
仓库当前网关与模块宿主默认连接 Redis `6397`。部署环境如果使用其他 Redis 服务端口,
由编排器同时覆盖双方的 `REDIS_PORT`,不能只修改一侧。独立模块宿主默认采用
`RPC_RUNTIME_MODE=all`,即同一进程同时接收 Action 并运行托管 Outbox/Inbox Worker
只有明确拆成 `rpc` 与 `worker` 两类副本时才覆盖该值,不能用兼容旧名称 `server`
冒充完整托管宿主。
生产环境由受信部署编排器在应用配置之外完成以下工作:
- 签发绑定精确 Build/Release 的 bootstrap ticket并注入 `BUILD_SHA`、Redis 和
RPC HMAC 材料Release 身份及摘要由控制面权威响应回填,不要求手工填写。
- 为每个副本分别挂载短期、一次性且绑定模块/Build/Release/制品的
`SAAS_RUNTIME_BOOTSTRAP_TOKEN_FILE`,不能让两个副本共用一个票据。票据签发结果会
同时返回并绑定该副本的 `instanceId`。
- 为每个副本提供独立、可写的 `SAAS_RUNTIME_BOOTSTRAP_STATE_FILE`;其中的实例 UUID、
Runtime Node ID、租约及 fencing 状态由 Runtime 管理,开发者不要手工填写。
- 使用票据签发结果中的 `instanceId` 生成对应的 `SAAS_TENANT_CREDENTIALS_FILE`,再与
票据一起挂载给该副本。源码和 Compose 文件都不能保存 Secret 值。
生产及其他严格环境不接受手工配置 `RPC_INSTANCE_ID`、`SAAS_RUNTIME_NODE_ID` 和
`SAAS_SERVICE_TOKEN_FILE` 来绕过 bootstrap。进程只能通过一次性 ticket 建立新会话,
或恢复 Runtime 已验真且仍有效的独占 state静态三元组仅作为 local/test 的迁移兼容,
不能用于部署。
`bootstrap.js` 会先执行 Runtime pre-bootstrap再校验精确 Release 环境,最后启动
Midway。`GET /health/` 读取 `rpcHostReadiness` 的真实快照bootstrap、Node ID 租约或
RPC 注册任一未就绪时都会返回 HTTP `503`,只有全部就绪才返回 `200`。
仓库根目录的 `docker-compose.microservices.yml` 是同镜像双副本示例。两个副本容器内
均使用 `7101`,并分别映射到宿主机 `17101`、`17102`,每个副本有独立的 bootstrap
ticket、tenant credential Secret 和 Runtime state volume。生产环境若只需容器网络
内的 readiness probe可以用部署 override 清空 `ports`Action RPC 不受影响:
```yaml
services:
demo-stable-a:
ports: []
demo-stable-b:
ports: []
```
Compose 顶层 Secret 的 `${..._FILE}` 是编排器生成的宿主机文件路径,不是应用配置。
这些源文件在 Linux 上必须限制为服务账户私有权限(例如 `0600`),且不能提交到
仓库。生产平台可等价替换为 Kubernetes/Swarm external Secret容器内的固定挂载路径
和 `*_FILE` 环境变量无需改变。
`SAAS_CONTROL_PLANE_URL` 必须是容器自身能够访问的地址;容器中的 `127.0.0.1` 指向
容器本身,不能用来表示宿主机或另一个控制面容器。生产环境必须使用 HTTPS。