feat: complete contract-driven business development and MySQL integration

This commit is contained in:
2026-09-24 21:56:04 +08:00
parent f9afb8f8dd
commit f5478cdc76
108 changed files with 6557 additions and 550 deletions

View File

@@ -0,0 +1,58 @@
# v0.14.0-preview 通用业务开发验收
验收日期:2026-09-24。范围为 go-omni 框架、生成消费者、隔离本地 MySQL;没有修改 eTax/ePay 业务,也没有连接既有业务服务器。本轮实现不内置业务字段、中文文案、表结构、权限或事务规则。
## 完成项与业务可移除的适配
| 能力 | 验收内容 | 接入项目可替换的通用代码 |
| --- | --- | --- |
| 根数组、可空对象、成功 null | 自动 Logic/Handler,nil 数组归一为 `[]`,可空对象与 null 保留,raw/统一公共体/204 分开验证 | 仅为响应形状存在的手写 Handler |
| 严格请求策略 | 未知 query、原始非法 UTF-8、charset、必填/可选/禁止 body、严格 `{}`、重复键、未知字段、分块限额及 413 | strictRequest、jsonEncoding、emptyJSON、query 白名单与从 OpenAPI 反读规则 |
| 声明式 multipart | 文件/文本/JSON DTO、普通字段校验先于 Logic、未知/重复/缺失/截断/各级超限、文件读者与临时文件清理 | FormFile/PostFormValue、手工 JSON 表单解码;仍保留资料内容检查 |
| 配置与校验 | 全结构体默认值→文件→环境、显式 0/false、空值策略、嵌套、duration/map/slice、敏感值不进入解析诊断、失败不污染默认配置 | 重复 LookupEnv/ParseBool/Atoi/ParseDuration 和框架日志校验 |
| 生命周期与日志 | 逆序清理、并发幂等关闭、失败回滚、清理 panic 后继续、依赖故障原因保留、排空先于释放、多 App Logger 隔离 | svc 的锁/once/清理栈、标准日志桥接、可信 ClientIP 搬运 |
| 依赖中间件与 context 错误 | 小接口工厂装配,标准 context 传递可信元数据;取消/超时映射尊重显式业务错误 | 为接入依赖而放进 context 的服务对象、重复 contextErrors |
| 字段文档与格式化 | 中文前置/同行注释、example/枚举说明;格式化保字面量与注释、字段对齐、幂等/只读 check;元数据不调用项目 scalar 解码器 | 常规接口的文档反射补丁、第二份手工维护的 OpenAPI |
| Go 错误目录文档 | 显式 ExportCatalog、严格元数据解码、参数/响应示例、独立路由目录优先,CLI 不执行项目 Go | 在 `.api` 重复维护 Go 错误表 |
| 多服务契约与升级 | roots/摘要、路径与符号链接边界、循环/深度/数量限制、分文件 DTO、独立 module 工作区;原模板升级、定制文件保护及失败回滚 | response.api 复制脚本、把整棵新生成目录手工拼回项目 |
| MySQL 接入 | 结构化配置、独立 TLS/双向 TLS、主机名与 CA 验证、连接池/会话/驱动日志隔离、启动检查、清理;继续复用标准 Connector | TLS 注册、驱动配置、建池/Ping/日志适配和通用失败清理;保留 SQL/版本和表结构策略 |
以上是可替换的职责,不是已删除 eTax 文件的声明。业务方应迁入等价契约/配置并通过自己的权限、金额和事务回归后,再移除旧适配。
## 本地回归
以下命令已通过:
```sh
GO_OMNI_SCAFFOLD_INTEGRATION=1 go test -race ./... -count=1 -timeout=300s
go vet ./...
go build ./...
go run ./cmd/go-omni api generate --dir examples/managedService --check
go run ./cmd/go-omni api format --api examples/contracts/business.api --check
git diff --check
python3 scripts/verifyManagedProject.py --report reports/businessDevelopmentManagedLocal.json
python3 scripts/verifyConnector.py --local --report reports/businessDevelopmentConnectorLocal.json
```
全量 race 包括框架既有网络层、错误继承/参数、桥接、上传下载回归,以及实际生成消费者。生成器集成包括 MySQL 与多种存储配置的编译/配置校验;不把这些编译测试称作云服务联调。
[生成进程报告](businessDevelopmentManagedLocal.json) 验证根目录 `go run .` / `go build .`、生成稳定性、业务保留、nethttp/native 的真实 HTTP、SIGINT/SIGTERM 和端口释放。消费者测试另外覆盖初始化/监听失败、依赖故障退出、排空后关闭、内置接口配置和 404/405。
[MySQL 报告](businessDevelopmentConnectorLocal.json) 使用仅绑定 localhost 的临时容器,限制 1 CPU、768 MiB、128 PIDs;临时凭据、CA、服务端与客户端证书在测试后移除。真实验证 TLS/mTLS、坏 CA/主机名拒绝、多个池隔离、会话设置与失败恢复,并复验 nethttp/native 读写超时。生成服务只改配置即可建池,并验证清理和借用 Logger 的所有权。
测试文件中的可选基础设施用例在普通 `go test` 下会跳过;上面的隔离数据库脚本显式开启它们,并拒绝测试级 skip。报告包含源码摘要用于追溯。
## 远程发布验收
代码发布标签后,使用以下命令在空 module 缓存验收同版远程 CLI/框架,不使用本地 replace;结果另行归档,发布标签不移动:
```sh
python3 scripts/verifyManagedRelease.py --version v0.14.0-preview --report reports/businessDevelopmentManagedRemote.json
python3 scripts/verifyConnector.py --version v0.14.0-preview --report reports/businessDevelopmentConnectorRemote.json
```
## 维护边界
用户维护 `.api`、业务配置、svc 字段/Init/AppOptions/DatabaseOptions、错误目录、Logic、Repository、权限中间件及特殊协议扩展。生成器管理 main、runtimeGen、路由/Handler、DTO 和文档。升级方法和完整示例见 [业务开发指南](../DEVELOPMENT.md)。
回归通过不等于具体业务已迁移。声明式上传使用临时磁盘,部署仍需限制请求并发和容量;清理函数必须自行停止并等待业务后台任务。框架不会回滚 Logic 已提交的业务事务;纯流式接口仍遵守 Complete 后再提交副作用的约定。特殊 scalar 的业务语义和自定义 Encoder 文档仍需项目验证。

View File

@@ -0,0 +1,74 @@
{
"passed": true,
"frameworkVersion": "v0.14.0-preview",
"localSource": true,
"frameworkSum": null,
"freshModuleCache": false,
"noLocalReplace": false,
"mysqlImage": "sha256:1afd25fe334a1be64a3866495dd43a6bdba3c55dd1d6190ea12933163fe2843c",
"mysqlLimits": {
"cpus": 1,
"memoryMiB": 768,
"pids": 128
},
"durationSeconds": 12.64,
"tests": [
"TestHTTPConfiguredStandardServer",
"TestHTTPInvalidStartupReleasesResources",
"TestHTTPConfiguredNetworkLimits/nethttp/slowHeaders",
"TestHTTPConfiguredNetworkLimits/nethttp/slowBody",
"TestHTTPConfiguredNetworkLimits/nethttp/idle",
"TestHTTPConfiguredNetworkLimits/nethttp/writeBackpressure",
"TestHTTPFileAndEnvironment/server.json",
"TestHTTPFileAndEnvironment/server.yaml",
"TestHTTPFileAndEnvironment",
"TestHTTPInvalidAndUnsupportedSettings/READ_HEADER_TIMEOUTinvalid",
"TestHTTPInvalidAndUnsupportedSettings/READ_HEADER_TIMEOUT-1",
"TestHTTPInvalidAndUnsupportedSettings/READ_TIMEOUTinvalid",
"TestHTTPInvalidAndUnsupportedSettings/READ_TIMEOUT-1",
"TestHTTPInvalidAndUnsupportedSettings/WRITE_TIMEOUTinvalid",
"TestHTTPInvalidAndUnsupportedSettings/WRITE_TIMEOUT-1",
"TestHTTPInvalidAndUnsupportedSettings/IDLE_TIMEOUTinvalid",
"TestHTTPInvalidAndUnsupportedSettings/IDLE_TIMEOUT-1",
"TestHTTPInvalidAndUnsupportedSettings/MAX_HEADER_BYTESinvalid",
"TestHTTPInvalidAndUnsupportedSettings/MAX_HEADER_BYTES-1",
"TestHTTPInvalidAndUnsupportedSettings",
"TestConnectorIndependentPoolsAndContext",
"TestConnectorRejectsInvalidInputWithoutTakingOwnership",
"TestConnectorStartupFailuresReleaseResources/connect",
"TestConnectorStartupFailuresReleaseResources/ping",
"TestConnectorStartupFailuresReleaseResources",
"TestConnectorTimeoutBoundsConnectAndPing/connect",
"TestConnectorTimeoutBoundsConnectAndPing/ping",
"TestConnectorTimeoutBoundsConnectAndPing",
"TestConnectorHealthBoundsPoolWaitAndRecovers",
"TestConnectorIdleZeroAndLifetime/noIdle",
"TestConnectorIdleZeroAndLifetime/expired",
"TestConnectorIdleZeroAndLifetime",
"TestConnectorTransactionsKeepCommitAndRollbackSemantics",
"TestMySQLConnectorDriverLoggerIsolation",
"TestMySQLConnectorTLSAndPoolIsolation/untrustedCA",
"TestMySQLConnectorTLSAndPoolIsolation/wrongHostname",
"TestMySQLConnectorTLSAndPoolIsolation",
"TestHTTPConfiguredNetworkLimits/nethttp/headerLimit",
"TestHTTPConfiguredNetworkLimits/nethttp",
"TestHTTPConfiguredNetworkLimits/native/slowHeaders",
"TestStructuredMySQLAdapterTLS",
"TestHTTPConfiguredNetworkLimits/native/slowBody",
"TestHTTPConfiguredNetworkLimits/native/idle",
"TestHTTPConfiguredNetworkLimits/native/writeBackpressure",
"TestHTTPConfiguredNetworkLimits/native/headerLimit",
"TestHTTPConfiguredNetworkLimits/native",
"TestHTTPConfiguredNetworkLimits",
"TestGeneratedMySQLConfigurationAndLifecycle"
],
"sourceHashes": {
"database/connector_test.go": "0663dfc9794ba24130225fa3b6418a6d5f75d57d0f01686151f70c7ea3f592c0",
"database/mysqlConnector_test.go": "e1cdd11ef76b09f1332ba92bfdde5b1917d84c85cc42fac48f65a8b23f5e9720",
"app/httpConfig_test.go": "b060dc0b76fb8e5feebae7e3b12cb7bca845693fcc097e2a0496a5ba937c837a",
"config/http_test.go": "0cae3dcf213369cfaff5487bf630c2bc3ec097739ca1d40794124e69c3880db8",
"database/mysql/integration_test.go": "05b0a73d50363eef760e8a3324a7e9a68c598f7519c6360ad530503178b56f43",
"scripts/verifyConnector.py": "4d2b1da0a1fcf641e02600710789ced51a58cf6fa1726a00c194a01f8e557e1a",
"scripts/testdata/mysqlGenerated_test.go": "5630123add5ed17f261c1a1bf63ba773f7fa6ea613fd573d5c5cb72da3e42645"
}
}

View File

@@ -0,0 +1,57 @@
{
"passed": true,
"mode": "localSource",
"durationSeconds": 4.43,
"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": "e0290bc5b6fdd9404da7944f2697299548ca3ea3611cf0e4a3ad3db5be2f7554",
"cmd/go-omni/apigen/templates.go": "88b96812e2f9ee57e22b15842268bbd8396d90f950191a72f1d75e987254f3ff",
"cmd/go-omni/apigen/startup.go": "e3322fa3e2aff9f45d66427f44187535c7c0960edc0f5fdfd5d7b4943b349334",
"cmd/go-omni/apigen/managed_test.go": "2b6bdf62a06cf25b85cbf06d60a5284ba24256c6705611fad4c012f63661a03d",
"cmd/go-omni/apigen/contractChanges.go": "aeb83990e908738faaa3cdfa20c3b8938023db05b6e55f2d24352c44144056a8",
"cmd/go-omni/apigen/logicCheck.go": "ca1af4f876a3a0db7b7b9ba9b82c1d6399fd89d29f667dad39cfd3de526eb1cb",
"cmd/go-omni/apigen/write.go": "180c5f5daee1441fe936cb376b1645a3d0c802cc78bf4b451dbf7e7b3e4ac0f4",
"cmd/go-omni/api.go": "5203a17c5f66977a9eba838d61cf5a7356de53d5f72a1196fd4f2046aa43ac85",
"config/config.go": "d2dc0b98bcce154957d760775906ca734b836b60852e1db34c93dbcc6c4b0bc3",
"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-config.go.tmpl": "fa37bd0a71587e2f821ec1595eb1f1a371677c90428001ea75f61815243c3b7b",
"cmd/go-omni/scaffold/templates/api-runtime.go.tmpl": "aacde854edd12a35cd97de41a449a306ec7bb6f245a0d62391d44e9a2ee1486b",
"cmd/go-omni/scaffold/templates/api-close.go.tmpl": "3f22d272e92f3b64b62123b3d80ec1a6ce8834257d64752fd75facf12623902b",
"cmd/go-omni/scaffold/templates/api-databaseOptions.go.tmpl": "6e5395b4a787c77a6cabfd85f16049a39578d6ec751a9b78203f3a03baabdf28",
"cmd/go-omni/scaffold/templates/api-options.go.tmpl": "11fe34ce45e8c98f7b5c9c0a2c512eb0b3abf86f95b4b576e083bcb6f5d0f824",
"cmd/go-omni/scaffold/templates/api-context.go.tmpl": "ac64c9134bf6f68cbd21b1974a31e3100d6f1c2751f2c3b6f35d6807037f41fa",
"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"
}
}