Files
supply-intelligence/tech/PRODUCTION_P0_P1_P2_BOARD_2026-05-08.md
2026-05-12 18:49:52 +08:00

7.9 KiB
Raw Permalink Blame History

Supply-Intelligence 生产上线 P0/P1/P2 收敛板2026-05-08

状态:当前有效 仓库:/home/long/project/立交桥/projects/supply-intelligence 目标:把当前已完成的 B2/B3/B4 实现闭环,继续推进到“可生产上线判定”所需的最小生产门禁。

0. 当前结论

当前结论REQUEST_CHANGES

已完成事实:

  • publish 已不再只是 event append已驱动 candidate test_passed -> published、package draft -> active
  • admission-state 已能反映 publish 后组合态以及 ack 后 gateway_sync_status 变化
  • 相关 targeted tests 已通过:
    • go test ./internal/publish ./internal/httpapi ./internal/app ./internal/repository

仍不能宣称可生产上线的原因:

  • PostgreSQL 持久化路径与内存仓储语义未收敛,当前 publish 主链路缺少数据库事务/并发保护证据
  • 发布幂等、重复发布、冲突发布、ack 重放/乱序等生产失败路径证据不足
  • 缺少基于 PostgreSQL 的真实端到端链路验证与上线证据包

1. 已复核事实基线

1.1 代码级事实

  • internal/publish/service.go 已存在 PublishDraft(ctx, PublishDraftInput) 主入口
  • internal/httpapi/server.go/internal/supply-intelligence/publish/package-event 已切到真实发布语义
  • internal/httpapi/admission_state_api_test.go 已验证 publish 后 published + active + pending 以及 ack 后 applied
  • internal/gatewayconsumer/service.go 已具备最小 consume-once -> ack -> snapshot 路径

1.2 当前生产差距(实测/读码得出)

  1. internal/repository/postgres.go
    • AppendPackageEventContext() 仍是 ON CONFLICT (event_id) DO NOTHING,但上层未把冲突解释为幂等成功/重复请求拒绝的明确产品语义
    • UpdateCandidateStatus()UpsertSupplyPackage()AppendPackageEventContext() 彼此独立执行,未处于同一数据库事务
    • 全文件未见 Begin/Commit/Rollback/FOR UPDATE,说明 publish 主链路当前没有 PostgreSQL 事务级一致性保护
  2. 目前通过的测试主要基于内存仓储;尚未看到 PostgreSQL 集成测试证明:
    • 并发双发布只会成功一次
    • 重复 event_id 的幂等语义稳定
    • package/candidate/event 在异常中不会出现部分提交
  3. 仓库虽已有 docker-compose.ymlmigrations/internal/repository/postgres.go,但未形成 production gate 所需的真实 E2E 证据链

2. 分级任务板

P0. 生产阻塞项(不上这些,不能判定可上线)

P0-1. PostgreSQL 发布事务原子化

  • OwnerEngineer
  • 目标:把 publish 主链路收敛为单事务提交,而不是多次独立写入
  • 代码落点:
    • internal/repository/interfaces.go
    • internal/repository/postgres.go
    • internal/publish/service.go
    • 可能新增 internal/repository/postgres_publish_tx_test.go
  • 必须达成:
    • candidate 状态更新、package 状态更新、event append 在同一 DB 事务中完成
    • 任一步失败时整体回滚
    • 明确重复 publish 的返回语义(幂等成功或冲突失败,必须固定)
  • 验证:
    • go test ./internal/publish ./internal/repository
    • 至少一条 PostgreSQL 集成测试证明回滚语义
  • 当前状态:completedPostgresRepository.PublishPackageAtomically 已实现 BEGIN/UPDATE/UPSERT/INSERT/COMMITTestPostgresPublishPackageAtomicallyRollsBackOnDuplicateEvent 通过

P0-2. 重复发布/并发发布保护

  • OwnerEngineer
  • 目标:防止同一 platform+model 或同一 draft package 被重复发布
  • 代码落点:
    • internal/publish/service.go
    • internal/repository/postgres.go
    • internal/repository/memory.go
    • 相关 *_test.go
  • 必须达成:
    • candidate 已 published 或 package 已 active 时再次发布,有明确拒绝/幂等语义
    • 并发双发布测试下,最终只能有一个成功结果
    • event 不可重复污染 downstream queue
  • 验证:
    • 并发测试 / 重复调用测试通过
  • 当前状态:completed — 已补充 TestPostgresPublishPackageAtomicallyConcurrentDoublePublish,验证并发双发布时仅一个成功、无脏数据

P0-3. PostgreSQL 真实链路 E2E

  • OwnerQA
  • 目标:在 PostgreSQL 环境下验证最小生产主链路
  • 链路candidate -> admission(test_passed) -> publish -> package-changes -> consume-once -> ack -> admission-state
  • 代码/资产落点:
    • 现有 docker-compose.yml
    • migrations/
    • 新增 internal/... PostgreSQL 集成测试或 scripts/ 验证脚本
  • 必须达成:
    • 不是仅 go test ./...,而是真实 PostgreSQL 状态可读回
    • admission-state 能反映 pending/applied/failed
    • gateway snapshot 与 event ack 状态一致
  • 验证:
    • 可复现命令 + 实际输出
  • 当前状态:completedTestPostgresE2EPublishConsumeAckAdmissionState 已覆盖完整链路,TestPostgresE2EPublishConsumeAckAdmissionStateRequiresAuthorizedConsumer 验证未授权消费过滤

P1. 上线前必须补齐项P0 完成后,仍建议上线前补齐)

P1-1. 失败补偿与错误语义收敛

  • OwnerTechLead -> Engineer
  • 目标:补明确的失败模型,而不是只靠 internal_error
  • 范围:
    • 发布冲突
    • event 已存在
    • ack 重放
    • ack 目标不存在
    • consumer apply failed 的重试/终态语义
  • 交付:错误码/状态机/handler 响应语义收敛
  • 验证:针对失败路径的 HTTP/API 测试
  • 当前状态:completed — 已有明确错误码(ErrInvalidPublishInput/ErrCandidateNotPublishable/ErrPackageNotPublishable/ErrDuplicatePublishRequest/ErrPackageAlreadyPublished、重试策略1m/5m/15m最多2次、终态定义applied/pending/failedconsumer 测试覆盖所有失败路径

P1-2. gateway consumer 生产约束验证

  • OwnerQA
  • 目标:验证 gateway 侧不是“最小骨架可跑”,而是生产语义可解释
  • 必查:
    • 未授权 account 过滤
    • pending-only 消费
    • apply failed 后状态可见
    • snapshot 与 event ack 不漂移
  • 验证definition -> assembly -> call -> entry 四层核查 + targeted tests
  • 当前状态:completedTestServiceConsumeOnceSkipsUnauthorizedEventsTestPostgresE2EPublishConsumeAckAdmissionStateRequiresAuthorizedConsumerTestServiceConsumeOnceFailedDoesNotDriftSnapshot 等已覆盖

P1-3. 上线证据包

  • OwnerXL
  • 目标:形成真正可用于上线判定的证据包
  • 必须包含:
    • 通过命令
    • 覆盖的关键链路
    • 明确未覆盖项
    • 可宣称项 / 不可宣称项
    • 回滚方式
  • 当前状态:completed — 已归档 reports/production/SHARED_ENV_EVIDENCE_RUN_2026-05-09.md 及 tksea 版本,含 G1-G3 证据

P2. 可上线后补项(不阻塞首版上线判定)

P2-1. actor / 审批链 / 审计增强

  • OwnerPM -> TechLead -> Engineer
  • 说明:当前 publish 语义可先无完整审批产品化,但上线后应补 actor、审批来源、审计追踪
  • 当前状态pending

P2-2. 真实远端 gateway 集成

  • OwnerDevOps/Engineer
  • 说明:当前 consume-once 仍偏本地 apply/ack 语义,后续应补真实下游系统契约
  • 当前状态:conditional_debt — 首版上线允许携带,必须在第一个迭代周期内补清(建议 2 周内)

P2-3. 观测与运行基线

  • OwnerDevOps
  • 说明:补指标、告警、日志字段、发布/ack 异常观测面
  • 当前状态pending

3. 推荐执行顺序

  1. P0-1 PostgreSQL 发布事务原子化
  2. P0-2 重复发布/并发发布保护
  3. P0-3 PostgreSQL 真实链路 E2E
  4. P1-1 / P1-2
  5. P1-3 上线证据包

4. 明确禁止的错误结论

  • 不得把内存仓储测试通过等同于 PostgreSQL 生产可用
  • 不得把 published 等同于 gateway applied
  • 不得把 ON CONFLICT DO NOTHING 视为已完成幂等设计
  • 不得把缺少事务保护的多次独立写入视为“发布事务已完成”
  • 不得在缺少 PostgreSQL E2E 证据时宣称可上线