feat(gateway): 图/视频调用经进程内 Gateway 做重试、Fallback 与观测 - #331
Conversation
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
并发过期不再 KeyError;跳过开路型号会记 fallback_used;视频分阶段耗时写入 trace;提交未拿到 job_id 时除 429 外不再换型号。 Co-authored-by: Cursor <[email protected]>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Review conclusion
整体分层与提交后不重复建单的主路径一致,但视频错误状态仍有两处会扩大重试或污染后续路由:轮询 52x 被 adapter 与 Gateway 双重重试,以及本次请求明确禁止 fallback 时仍提前打开型号熔断。建议修正这两个状态转换后再合入。
验证:完整检查了固定 diff 4103106...19fce6a 的 gateway、Sufy adapter、executor/API 接入与相关测试;git diff --check 通过。当前运行环境缺少 uv 和项目 Python 依赖,未能执行 pytest。
| elif step is NextStep.FALLBACK: | ||
| self._circuit.open("model:" + model) | ||
| circuit_scope = "model" |
There was a problem hiding this comment.
[P1] 仅在实际切换型号时打开型号熔断
这里在检查 fallback 是否允许之前就打开了 model:<model> 熔断。对于已经拿到 job_id 的轮询 429/无效响应,下面的保护分支会正确拒绝新建 fallback 单并立即失败,但熔断已经保留 60 秒;下一条独立任务会跳过仍可能正常的 primary,直接向 fallback 型号建单。提交阶段的无效响应也有同样问题。请把熔断更新移到通过 bound_job_id/错误类型保护、确定确实会 break 到下一个型号之后。
| resp = client.get(f"/videos/{job_id}") | ||
| if resp.status_code in (521, 522, 523, 525): | ||
| resp = client.get(f"/videos/{job_id}") |
There was a problem hiding this comment.
[P2] 避免轮询 52x 在两层各重试一次
_poll_get 已经在一次 follow_job 内对 521/522/523/525 连打两次,而 VideoGateway 收到最终 UNREACHED 后还会按同一策略再次调用 follow_job。因此持续 522 时同一个轮询点实际发出 4 次 GET,而不是描述和策略要求的“只再试一次”;trace 还只记录为一次 Gateway retry,无法反映真实请求数。请让 adapter 保持一次 GET,把唯一的重试预算交给 Gateway,或让 Gateway 知道 adapter 已消费该预算。
|
我的 #324 也改 sufy.py——抽了个 ChatCompletionsFace 让出图和判官共用建连和重试,和你这版重叠。你把重试整个移到 Gateway 之后那层就多余了,所以不管哪边先合,我都按你的 AdapterResult 收,不另起一套。 |
现按照我的来做吧。咱们把重试的逻辑统一放在gateway做,这样方便后续的链路追踪、熔断、限流等逻辑的引入,以及更换模型路由。这样看起来,重试逻辑也不会太过散乱,你觉得呢? |
5b57caf to
b782d7d
Compare
Summary
sufy.py抽到windup_framework.gateway。业务仍只调ImageProvider.gen_image/VideoProvider.i2v。job_id后不再 POST 第二单,仅failed/cancelled允许换型号新开。request_id,便于从日志捞 attempt 链。积分扣费仍走现有QUOTA_*。Fixes #330
Test plan
backend/下 gateway + sufy + custom_action + executor 等相关测试 167 passedjob_id后,轮询 429/失败不再开第二单;上游failed/cancelled才换型号video_model仍 4xxrequest_id=