Skip to content

分页/status 不变量剩余 5 项:clamp 可观测性待产品裁决 + 改名 + repo 非正值→500 + openapi 缺口 #2243

Description

@DeliciousBuding

来源:round-64 lane D 只读探索(#2241),锚点在 42ba064c 逐行核实,主机侧已抽验复现(P1-1 实测 ClampPageSize 在 handler 包命中 = 0、手写 clamp 文件数 = 10、constants.go 两条 MUST 原文已核对)。

问题:同一个不变量/默认值有多份互相矛盾的定义,且专门的 helper 被整层绕过

切片 1:分页天花板三份定义打架

  • hub-server/internal/config/constants.go:20-25 MaxListPageSize = 200,注释自称「是 api/openapi.yaml 为共享 PageSize 参数声明的值,所以是那些端点必须实际执行的界」
  • hub-server/internal/config/constants.go:27-30 MaxPageLimit = 500,注释自称「所有 Hub handler 的 list 端点 MUST 夹到这个天花板」
  • api/openapi.yaml:7592-7599 共享 PageSize 参数 maximum: 200
  • hub-server/internal/config/paging.go:11-33 ClampPageSize 正是为消灭这类散落而写,paging_test.go:48 还把 MaxListPageSize == 200 钉成契约测试

实测:grep -rln "ClampPageSize(" hub-server/internal/handler | wc -l = 0(14 个调用点全在 repository/service);grep -rln "if pageSize > config.Max" hub-server/internal/handler | wc -l = 10skill.go:98 / market.go:46 / session.go:343 / workspace.go:88 / mcp_server.go:104 / provider_binding.go:46 / execution_target.go:235 / agent_team_runs.go:125 / agent_profile.go:152 / message.go:412)。

后果:handler 层放行到 500、repository 层再夹到 200 ⇒ pageSize=300 拿回 200 行 + HTTP 200 + 无任何信号。这正是 paging.go:16-17 自己写下要消灭的行为("turns 'you asked for too many' into 'here is a quarter of a page', with HTTP 200 and no error")。OpenAPI 声明的 200 在「声称执行它的那一层」根本没执行。

修法:10 个 handler 的 6 行两分支 → pageSize = config.ClampPageSize(pageSize, config.MaxListPageSize, config.DefaultPaginationLimit)message.goMaxMessagePageLimit);删掉 MaxPageLimit 或改名/改注释为 document 家族专用,消掉两条 MUST 冲突;顺手把 8 处 DefaultQuery("pageSize", "50") 字面量统一为 strconv.Itoa(config.DefaultPaginationLimit)(已有 3 处这么写)。写集 ≈11 文件 / 60 行。

切片 2:*Error.HTTPStatus != 0 这一个不变量有 4 种处置

  • pkg/errcode/error.go:68-71 New(code, message, httpStatus) 不兜底,0 照收
  • hub-server/internal/handler/response.go:31-34 clamp → 500
  • hub-server/internal/middleware/response.go:15-18 clamp → 500
  • hub-server/internal/middleware/timeout.go:270-273 clamp → 504(与上面两处不一致)
  • pkg/errcode/error.go:101-117 WriteError 完全不 clamp

实测:8 个非测试 errcode.New( 调用点全部传显式非 0 状态,codes.go 里 17 个 &Error{} 字面量全部带 HTTPStatus;只有 2 个测试传 0(middleware/rate_limit_test.go:130middleware/response_test.go:73)⇒ 3 处 clamp 目前只被测试保持存活,而走 WriteError 的路径拿到 0 状态就没人管。

修法:不变量在构造处成立一次——Newif httpStatus == 0 { httpStatus = http.StatusInternalServerError },删掉 3 处 clamp,2 个「传 0」测试改成断言新语义。写集 ≈5 文件 / 20 行。

注:round-62 记录的「9 处 500 clamp」在 42ba064c 上只穷举到 3 处(edge 侧 0 处);本 issue 按实测的 3 处写,不沿用旧数字。

验收

  • 两个切片可各自独立成 PR,写集不重叠
  • pageSize=300 的行为必须有明确断言(夹到 200 且有信号,或按产品裁决改为 400)——不许继续静默
  • 契约测试 paging_test.go 保持绿;go test ./internal/config/ ./internal/handler/ ./internal/middleware/pkg/errcode 全绿
  • verify-openapi-contract.py 若 pageSize 语义变化需同步(当前基线 153/156/3/0)

负向约束

  • 不许改既有测试的既有断言来迁就实现(round-64 lane A 就是因为这条才没照抄 diff_apply.go 的门形态)
  • 不许顺手把 edge 也加分页 clamp(edge 无此概念,0 命中)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions