feat: add dependency shutdown and configurable service endpoints
This commit is contained in:
49
performance/lifecycleEndpointsAcceptance.md
Normal file
49
performance/lifecycleEndpointsAcceptance.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# 依赖主动退出与内置接口配置验收
|
||||
|
||||
日期:2026-09-24;环境:Go 1.27.1,darwin/arm64;目标版本:v0.13.0-preview。
|
||||
|
||||
## 验收范围
|
||||
|
||||
- 通用生命周期控制器连接项目依赖与生成入口。项目决定故障是否需要退出;框架不判断 ID 租约或其他业务规则。
|
||||
- `svc.RequestShutdown(err)` 立即通知并保留首个非空原因,生成入口排空 HTTP 后关闭依赖与日志;重复或并发通知不会重复清理。
|
||||
- 生成项目通过 `server.endpoints` 控制 liveness、readiness、OpenAPI 的开关与路径。健康检查默认使用项目响应模板和错误目录,可显式选择 raw 数据。
|
||||
- 就绪失败固定 HTTP 503,即使项目业务错误统一使用 HTTP 200;原始探针错误保留给日志,不进入公开响应。OpenAPI 不包装公共体。
|
||||
|
||||
## 源码与实际生成项目
|
||||
|
||||
回归命令:
|
||||
|
||||
```sh
|
||||
GO_OMNI_SCAFFOLD_INTEGRATION=1 go test -race -p=1 -count=1 -timeout=300s ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
python3 scripts/verifyManagedProject.py --report performance/lifecycleEndpointsLocal.json
|
||||
```
|
||||
|
||||
最终全量 race 测试(包括生成器集成测试)、go vet、go build 全部通过;修改文件的 gofmt、Python 语法、文档本地链接及 git diff --check 通过,本地报告的源码哈希与发布源码一致。
|
||||
|
||||
- `lifecycle` 测试覆盖并发通知、正常停止后报告故障、初始化前通知、父 context 原因,以及包装 context.Canceled 的显式故障。
|
||||
- `TestFatalShutdownDrainsAndPreservesCause` 在 nethttp/native 上验证:在途请求完成前不关闭依赖,关闭仅一次,故障和清理错误都保留;提前取消的启动同样保留故障。
|
||||
- `TestManagedGeneratedProject` 使用实际 CLI 生成的 main/Handler/DTO,在项目文件中加入模拟客户端和配置,子项目执行 race 测试与根目录构建。新增子测试验证依赖通知后的排空顺序、初始化期间通知、端点配置、冲突后的资源释放。
|
||||
- `TestGeneratedFatalProcessExit` 启动真实子进程执行生成的 main:故障退出码为 1,输出保留实际原因,模拟客户端只关闭一次。
|
||||
- 健康测试覆盖数字 code、项目 msg、成功模板、NOT_READY 目录映射、raw 数据、关闭中的 readiness、失败日志状态与内部原因。目录的 HTTP 200 和自定义 Encoder 都不能把未就绪改成 HTTP 200;编码器出错或 panic 时也不会误报健康。
|
||||
- 配置测试覆盖默认值合并、显式 false、环境变量、非法路径/模式、重复端点及业务参数/通配路径冲突。`TestConfigurableBuiltinRoutesConsumer` 用真实生成项目验证:默认冲突明确报错;禁用或改名后项目可接管原路径。
|
||||
- 原生成项目回归继续覆盖 Go 错误目录继承、模板参数、404/405、中间件错误、raw body、multipart 上传、流式下载、初始化/监听失败清理、业务文件保留和生成漂移检查。
|
||||
- [本地真实进程报告](lifecycleEndpointsLocal.json) 最近一轮通过,耗时 4.33 秒,记录验收源码哈希;根目录 go run/go build、nethttp/native 的 SIGINT/SIGTERM、端口释放及上传下载请求均通过。二进制正常信号退出码为 0;go run 包装进程允许被信号终止,子服务必须退出并释放端口。
|
||||
- 源码示例 `examples/managedService` 编译、race 测试与 `api generate --check` 通过;示例保留相对 replace 以运行本地源码。远程验收会重新生成无 replace 的项目。
|
||||
|
||||
## 验证过程中修正的问题
|
||||
|
||||
真实进程验收发现 Go 1.27 的 signal.NotifyContext 使用可匹配 context.Canceled 的信号原因;精确相等判断会把正常信号误报为故障。生命周期现在使用 errors.Is 识别正常取消,同时 Controller 单独保留项目显式报告的非空错误。修正后两种网络层的 SIGINT/SIGTERM 退出验证通过。
|
||||
|
||||
一次全量测试中,S3 协议夹具的故意损坏请求触发 SDK 随机重试,耗尽共享测试期限。仅将测试自建客户端设置为一次尝试,生产客户端配置保持不变,并单独检查 Open 创建的客户端可访问夹具;连续三次 race 回归通过。此调整不改变存储运行时行为。
|
||||
|
||||
## 升级与边界
|
||||
|
||||
v0.12 项目的 svc/config 是开发者文件,重新生成仍会保留。升级需按 [PROJECT.md](../PROJECT.md#从-v012-生成项目升级) 在 svc 增加 Lifecycle、RequestShutdown 和清理衔接;main/Handler 由生成器自动更新。新项目直接获得这些扩展。
|
||||
|
||||
请求排空使用已有 shutdownTimeout;忽略 context 的业务 goroutine 无法被框架强制结束,项目 Close 必须停止并等待自建监控任务。内置接口继续经过全局中间件,访问规则由项目设置。
|
||||
|
||||
没有修改 eTax/ePay,也未连接业务服务器、真实数据库或云存储。所有服务与子进程均在本地临时环境验收并回收;本轮不是压力测试或业务迁移验收。
|
||||
|
||||
远程安装验收在不可变标签发布后执行,报告单独提交,不改写标签。
|
||||
54
performance/lifecycleEndpointsLocal.json
Normal file
54
performance/lifecycleEndpointsLocal.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"passed": true,
|
||||
"mode": "localSource",
|
||||
"durationSeconds": 4.33,
|
||||
"checks": [
|
||||
"rootGoRun",
|
||||
"rootGoBuild",
|
||||
"stableRegeneration",
|
||||
"checkMainOwnership",
|
||||
"contractChangePreview",
|
||||
"logicSignatureCheckPersists",
|
||||
"businessSourcePreserved",
|
||||
"fixedConsumerBuild",
|
||||
"nethttpSIGINT",
|
||||
"nethttpSIGTERM",
|
||||
"nativeSIGINT",
|
||||
"nativeSIGTERM",
|
||||
"listenerReleased",
|
||||
"temporaryProcessesRemoved",
|
||||
"nethttpGeneratedTransfers",
|
||||
"nativeGeneratedTransfers",
|
||||
"malformedMultipart400",
|
||||
"goOwnedErrors",
|
||||
"default404And405"
|
||||
],
|
||||
"sourceHashes": {
|
||||
"cmd/go-omni/apigen/generate.go": "c1808f5aff5c0475859f808e52ae29d7ac4234ecf2f784073c93bfee5bb7a2b7",
|
||||
"cmd/go-omni/apigen/templates.go": "ec73080836763bbe60721351295df8471ed93691c62766172238ea1df390215e",
|
||||
"cmd/go-omni/apigen/startup.go": "ea6d671a2e580911cdb954b96356e401f0f98bc41fb9e7b0c30239222fce923f",
|
||||
"cmd/go-omni/apigen/managed_test.go": "ff9ce6e9fa6cff63c8b52f5e0c43879f9b08b5750ab72b617d32bec114d955da",
|
||||
"cmd/go-omni/apigen/contractChanges.go": "ea190447e4260e0b3f3d28554ae61eac73f289aab601a16c7521dabc59fd736f",
|
||||
"cmd/go-omni/apigen/logicCheck.go": "9fa1aa8cfef3a7b54dc5afb9b4320ec4e86ea5b46fc03705505216921279fa04",
|
||||
"cmd/go-omni/apigen/write.go": "e415bb1e2db4674c5de7c81681b26a71925ddadbd647903b72674555e54911f1",
|
||||
"cmd/go-omni/api.go": "eac8ed809000a939e3dfa7e3c01af67a26c705306143654a6b5a8e8733f2ab13",
|
||||
"config/config.go": "9933e6ac581d75907afa1285440b61b7d5729d0ac0ce761cd8255473fd7e6028",
|
||||
"httpx/transfer.go": "c9fe4e98c0e599d367eaf19ebecf367db914edfca9ad3a65527496d1dea80a3d",
|
||||
"httpx/multipart.go": "b942ede7a810b268cd43b395c3bddcfaaacad92812bbb60e653466b8d86bc875",
|
||||
"scripts/verifyManagedProject.py": "b0e4b1aea4f44d61470c35c41f971e0882ae36b0eb5df2be190400d62fc60a18",
|
||||
"lifecycle/controller.go": "1fb9393df1908afed93d87a1bf3ecea8d79d78e437a656b56bb7f1e5f6e51d31",
|
||||
"health/health.go": "41f07f27a7fdcfa7973c2c554a22b73129ebc5d44e945e70e054e1cff24ab866",
|
||||
"config/endpoints.go": "9f5123f962d52b71e5b73d5942316170875e895129a94e8b669ce782969ef27d",
|
||||
"httpx/response.go": "2cf78b8f0eee8049ee612bb409a6eecc1d39eab9ab8f3b533ea21e3cac1611cb",
|
||||
"app/app.go": "e5255ffdd36cba1c155037afc42f1c921b1f91bc79db75798a7feb0e9d51b1c0",
|
||||
"app/transport.go": "88212d67d375e4c48c250a2e4c62fbff4e7873a67f91f2deb113a60634149f73",
|
||||
"cmd/go-omni/scaffold/templates/api-close.go.tmpl": "3f22d272e92f3b64b62123b3d80ec1a6ce8834257d64752fd75facf12623902b",
|
||||
"cmd/go-omni/scaffold/templates/api-options.go.tmpl": "11fe34ce45e8c98f7b5c9c0a2c512eb0b3abf86f95b4b576e083bcb6f5d0f824",
|
||||
"cmd/go-omni/scaffold/templates/api-context.go.tmpl": "c68f553e2500a395d77aa20c7b962fa257c47ef71b3ad36324413821b36ca0ec",
|
||||
"cmd/go-omni/apigen/testdata/managed/options.go": "30d48e4b5aab476c887ac53cc89b48b2b7e250c8cd25e55fecb49bb2a3589247",
|
||||
"cmd/go-omni/apigen/testdata/managed/client.go": "db886c2d4dd27e67f7446265c20147335d4898d2d2091518e67403806ccd9b69",
|
||||
"cmd/go-omni/apigen/testdata/managed/shutdown_test.go": "79fbf8dd4508b8217af888a31aaf2f2a01c1fa3869b2e80420605af697c66319",
|
||||
"cmd/go-omni/apigen/testdata/managed/consumer_test.go": "9e103c9de7a1a906903bc09787e1b38905dc5bb4d891c88938028da5dee98f6f",
|
||||
"cmd/go-omni/apigen/testdata/managed/operations.go": "44cea63e6023458c5818c9fdae223631cd1721f0841e671457398bfde8bc48f1"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user