Files
supply-intelligence/reports/qa/QA_GATEWAY_CLOSURE_DESIGN_REVIEW_2026-05-08.md
2026-05-12 18:49:52 +08:00

11 KiB
Raw Permalink Blame History

QA 设计审查报告Gateway 收口2026-05-08

阶段门控结论REQUEST_CHANGES 是否可进入 Engineer 实现:否

审查范围

  • PM 收口文档:/home/long/project/supply-intelligence/prd/PM_GATEWAY_CLOSURE_PRD_2026-05-08.md
  • TechLead 设计:/home/long/project/supply-intelligence/tech/TECHLEAD_GATEWAY_CLOSURE_DESIGN_2026-05-08.md
  • 真源索引:/home/long/project/supply-intelligence/tech/CURRENT_SOURCE_OF_TRUTH_2026-05.md
  • 消费闭环决议:/home/long/project/supply-intelligence/tech/GATEWAY_CONSUMER_DECISION_2026-05.md
  • 收口执行板:/home/long/project/supply-intelligence/tech/PRODUCTION_LAUNCH_CLOSURE_BOARD_2026-05-08.md
  • 真实代码链路抽检:
    • /home/long/project/supply-intelligence/internal/httpapi/server.go
    • /home/long/project/supply-intelligence/internal/gatewayconsumer/service.go
    • /home/long/project/supply-intelligence/internal/poller/gateway_package_poller.go
    • /home/long/project/supply-intelligence/internal/poller/runtime.go
    • /home/long/project/supply-intelligence/internal/publish/service.go
    • /home/long/project/supply-intelligence/internal/repository/interfaces.go
    • /home/long/project/supply-intelligence/internal/repository/postgres.go
    • /home/long/project/supply-intelligence/internal/metrics/metrics.go
    • /home/long/project/supply-intelligence/internal/app/app.go
    • /home/long/project/supply-intelligence/internal/httpapi/postgres_e2e_test.go

设计覆盖检查

  1. 契约边界:已覆盖
  • PM/TechLead 均明确了 published != applied、pending/applied/failed 语义。
  • 证据PM 文档 4.2/4.3TechLead 文档 2.2/2.3。
  1. 失败重试:部分覆盖,未闭合
  • PM 定义了可重试/不可重试、3 次上限、退避窗口。
  • TechLead 也识别出现有代码缺少重试元数据和重试结构。
  • 但设计仍停留在建议层,未与现有接口/表结构形成可执行的最小实现闭环。
  • 证据TechLead 3.2~3.7。
  1. 灰度/回滚:部分覆盖,缺少可执行入口
  • PM 给出暂停/回滚判定线。
  • TechLead 提出 runbook 脚本与 runtime pause/resume API 建议。
  • 但当前真实代码没有 runtime-status/pause/resume 入口,也没有脚本文件。
  • 证据server.go 仅有 /gateway/consume-once 和 health/metrics 等路径;未见 runtime control 路由。
  1. 巡检门禁:部分覆盖,缺少真实指标接入
  • 文档定义了 24h/72h 巡检项。
  • 但 metrics.go 只是声明指标,调用链中没有任何实际打点。
  • 证据metrics.go全文搜索未命中 GatewayEventsProcessedTotal / GatewayEventLatencySeconds 的使用点。

风险与保护检查

  • 风险 1发布完成与消费完成仍可被误判

    • 保护admission-state 暴露 last_event.gateway_sync_status且 E2E 覆盖 publish -> consume -> ack。
    • 缺口failed 重试后如何重新进入自动消费未实现。
  • 风险 2失败分类不足导致重试/终态策略无法落地

    • 保护:文档已定义失败分类模型和上限。
    • 缺口:代码层无 retry_count / next_retry_at / failure_category 持久化字段,无对应 repository 方法。
  • 风险 3无法暂停放量或受控回滚

    • 保护poller/runtime 已有 Start/Stop。
    • 缺口:没有 pause/resume 或 runtime-statusStop 是进程级粗粒度停机,不符合 runbook 设计要求。
  • 风险 4观测不可执行

    • 保护:/metrics 存在。
    • 缺口指标未接调用链无法支撑“15 分钟 applied 比例 < 95%”等门禁判断。

交接物可用性

  • 可用:
    • 发布、拉取、ack、admission-state 的基础闭环存在。
    • 真实代码路径可定位,且有 PostgreSQL E2E 证明基本链路。
  • 不足:
    • 缺少可执行 runbook 文件。
    • 缺少桌面演练 / 巡检 / 回滚脚本。
    • 缺少 runtime 控制接口。
    • 缺少重试状态持久化与失败分类存储。

关键调用链路核查(定义 / 装配 / 调用 / 入口)

链路 Apackage 发布

  • 定义:/home/long/project/supply-intelligence/internal/publish/service.go
    • PublishDraft / RecordPackagePublished
  • 装配:/home/long/project/supply-intelligence/internal/app/app.go
    • buildApp() 注入 publish.NewService(repo)
  • 调用:/home/long/project/supply-intelligence/internal/httpapi/server.go
    • handlePublishPackageEvent() -> publishService.PublishDraft(...)
  • 入口:/home/long/project/supply-intelligence/internal/httpapi/server.go
    • Route: POST /internal/supply-intelligence/publish/package-event
  • 结论:已闭合

链路 Bpackage changes 拉取

  • 定义:/home/long/project/supply-intelligence/internal/repository/interfaces.go
    • ListPackageEventsAfter
  • 装配:/home/long/project/supply-intelligence/internal/app/app.go
    • gatewayconsumer.NewService(repo)
  • 调用:/home/long/project/supply-intelligence/internal/httpapi/server.go
    • handleListPackageChanges() -> repo.ListPackageEventsAfter(...)
    • gatewayconsumer.Service.ConsumeOnce() -> repo.ListPackageEventsAfter(...)
  • 入口:/internal/supply-intelligence/gateway/package-changes
  • 结论:已闭合,但仅支持 cursor 流读取,不支持 retry due filtering

链路 Cack 回写

  • 定义:/home/long/project/supply-intelligence/internal/repository/interfaces.go
    • AckPackageEvent
  • 装配:/home/long/project/supply-intelligence/internal/app/app.go
    • gatewayconsumer.NewService(repo)
  • 调用:/home/long/project/supply-intelligence/internal/httpapi/server.go::handleAckPackageChange
    • repo.AckPackageEvent(...)
    • /home/long/project/supply-intelligence/internal/gatewayconsumer/service.go::ConsumeOnce
    • repo.AckPackageEvent(...)
  • 入口POST /internal/supply-intelligence/gateway/package-changes/{event_id}/ack
  • 结论:已闭合

链路 D默认消费方与 poller/runtime

  • 定义:/home/long/project/supply-intelligence/internal/gatewayconsumer/service.go::ConsumeOnce
  • 装配:/home/long/project/supply-intelligence/internal/app/app.go
    • NewGatewayPackagePoller(gatewayConsumerService)
    • NewRuntime(gatewayPoller, time.Second)
  • 调用:/home/long/project/supply-intelligence/internal/poller/gateway_package_poller.go::PollOnce
    • p.consumer.ConsumeOnce(...)
  • 入口:/home/long/project/supply-intelligence/internal/poller/runtime.go::Start
    • 周期定时触发 PollOnce
  • 结论:已闭合,但运行时只能 start/stop不能按 runbook 语义暂停/恢复

链路 Eadmission-state

  • 定义:/home/long/project/supply-intelligence/internal/httpapi/server.go::handleModelAdmissionState
  • 装配:/home/long/project/supply-intelligence/internal/app/app.go
  • 调用server.go 内直接读取 repo.GetLatestDiscoveryCandidateContext / GetSupplyPackage / GetLatestPackageEvent
  • 入口GET /internal/supply-intelligence/models/{platform}/{model}/admission-state
  • 结论:已闭合,适合作为发布后状态核验入口

问题清单

Critical

  1. 缺少重试状态机的真实持久化与调度闭环
  • 证据tech/TECHLEAD_GATEWAY_CLOSURE_DESIGN_2026-05-08.md 3.2~3.7 仅为建议internal/repository/interfaces.go 仅有 AckPackageEvent没有 retry_count/next_retry_at/get retryable pending 接口internal/repository/postgres.go AckPackageEvent 只更新 ack_status/consumer/detail/time。
  • 影响PM 定义的 3 次自动重试、退避、终态 failed 无法按设计执行。
  • 结论:阻断进入实现。
  1. 缺少可执行的灰度/回滚运行时控制入口
  • 证据server.go Routes 未暴露 runtime-status/pause/resumeruntime.go 仅有 Start/Stopapp.go 仅在启动时自动 StartBackground。
  • 影响:无法按 PM 要求执行“暂停放量但不立即回滚”“受控恢复”等门禁动作。
  • 结论:阻断进入实现。
  1. 观测指标未接入真实调用链
  • 证据internal/metrics/metrics.go 声明了 GatewayEventsProcessedTotal/GatewayEventLatencySeconds/AccountsByStatus/RoutingEnabledAccounts全文搜索未命中这些指标的实际使用点。
  • 影响:无法验证 15 分钟 applied 比例、重试积压、失败趋势等关键门禁。
  • 结论:阻断进入实现。

Important

  1. 失败分类模型未落地到 repository/domain
  • 证据TechLead 3.3 仅建议新增 failure category 枚举;当前 domain/repository 未见对应字段或接口。
  • 影响retryable/non-retryable 分流只能靠 consumer 内部临时判断,无法审计与追踪。
  1. 已失败事件缺少再次进入自动重试的机制
  • 证据TechLead 2.4 指出 ListPackageEventsAfter 会返回 failed 事件,但 consumer 仅消费 pendinggatewayconsumer/service.go 124-126 明确跳过 non-pending。
  • 影响failed 一旦写回后不可恢复自动重试,和 PM 的“人工处置入口/受控重试”设计不一致。
  1. runbook 依赖脚本文件但仓库中未见对应交付物
  • 证据TechLead 4.2 建议新增 scripts/gateway_closure_smoke.sh / inspect.sh / rollback.sh 和 runbook 文档;当前未发现这些文件。
  • 影响:交接物不可直接执行,只能纸面审查。
  1. PM 文档中的 24h/72h 巡检指标部分仍偏结果导向,缺少来源字段定义
  • 证据PM 7.1/7.2 仅描述“持续增长/稳定/是否出现”,未绑定具体采样接口与阈值归属。
  • 影响QA 与 Engineer 容易产生不同解释。

Minor

  1. 真源索引文件路径存在历史仓库前缀表述差异
  • 证据:/home/long/project/supply-intelligence/tech/CURRENT_SOURCE_OF_TRUTH_2026-05.md 第 5 行出现“/home/long/project/立交桥/projects/supply-intelligence/”。
  • 影响:容易造成阅读者路径混淆。
  1. TechLead 文档中提议的指标命名与现有 metrics 命名风格不完全一致
  • 证据3.2/5.2 建议使用 supply_intelligence_gateway_* 命名;现有 metrics 已有 supply_intelligence_ 前缀但具体标签规划未统一。
  • 影响:实现时需统一命名规范,避免重复与歧义。

Gap Taxonomy Summary

  • Contract gappublished/pending/applied/failed 语义已定义,但 retry/终态语义未形成代码闭环。
  • Execution gap灰度、暂停、回滚需要 runtime control 与脚本,当前只有基础 Start/Stop。
  • Observability gap指标声明存在实际打点不存在。
  • Data-model gap缺少 retry_count、next_retry_at、failure_category 等字段。
  • Operational gaprunbook 交付物缺失,无法直接演练。
  • Verification gap有 E2E 证明基础闭环,但没有覆盖失败重试/回滚/巡检门禁的实证。

最终门禁结论

  • 设计覆盖:部分通过
  • 风险保护:不足
  • 交接可用性:不足
  • 阶段门控结论REQUEST_CHANGES
  • 是否可进入 Engineer 实现:否

备注

本次审查已抽样核查真实调用链不是仅基于文档判断但由于重试、runtime control、observability 三条主链仍未在代码层闭合,因此不能给 APPROVED。