Skip to content

feat(gateway): 图/视频调用经进程内 Gateway 做重试、Fallback 与观测 - #331

Open
xiaocheny214 wants to merge 12 commits into
1024XEngineer:mainfrom
xiaocheny214:feat/llm-gateway
Open

feat(gateway): 图/视频调用经进程内 Gateway 做重试、Fallback 与观测#331
xiaocheny214 wants to merge 12 commits into
1024XEngineer:mainfrom
xiaocheny214:feat/llm-gateway

Conversation

@xiaocheny214

@xiaocheny214 xiaocheny214 commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • 把图生图和 i2v 的重试、同家族 Fallback、熔断和结构化 trace 从 sufy.py 抽到 windup_framework.gateway。业务仍只调 ImageProvider.gen_image / VideoProvider.i2v
  • 521/522/523/525 同型号只再打一次、不换型号;520/524 不重试。视频有 job_id 后不再 POST 第二单,仅 failed/cancelled 允许换型号新开。
  • 任务失败原因带上 request_id,便于从日志捞 attempt 链。积分扣费仍走现有 QUOTA_*

Fixes #330

Test plan

  • backend/ 下 gateway + sufy + custom_action + executor 等相关测试 167 passed
  • 图像 522:同一型号恰好 2 次 POST,不打 fallback 型号
  • 图像 429:primary 最多 3 次后走 fallback
  • 图像 520:只打 1 次
  • 视频 submit 拿到 job_id 后,轮询 429/失败不再开第二单;上游 failed/cancelled 才换型号
  • 非法 video_model 仍 4xx
  • 失败任务的 error 含 request_id=

@vercel

vercel Bot commented Aug 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
windup Ignored Ignored Preview Aug 19, 2026 4:44am

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review conclusion

整体分层与提交后不重复建单的主路径一致,但视频错误状态仍有两处会扩大重试或污染后续路由:轮询 52x 被 adapter 与 Gateway 双重重试,以及本次请求明确禁止 fallback 时仍提前打开型号熔断。建议修正这两个状态转换后再合入。

验证:完整检查了固定 diff 4103106...19fce6a 的 gateway、Sufy adapter、executor/API 接入与相关测试;git diff --check 通过。当前运行环境缺少 uv 和项目 Python 依赖,未能执行 pytest。

View job run

Comment on lines +190 to +192
elif step is NextStep.FALLBACK:
self._circuit.open("model:" + model)
circuit_scope = "model"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 仅在实际切换型号时打开型号熔断

这里在检查 fallback 是否允许之前就打开了 model:<model> 熔断。对于已经拿到 job_id 的轮询 429/无效响应,下面的保护分支会正确拒绝新建 fallback 单并立即失败,但熔断已经保留 60 秒;下一条独立任务会跳过仍可能正常的 primary,直接向 fallback 型号建单。提交阶段的无效响应也有同样问题。请把熔断更新移到通过 bound_job_id/错误类型保护、确定确实会 break 到下一个型号之后。

Comment on lines +93 to +95
resp = client.get(f"/videos/{job_id}")
if resp.status_code in (521, 522, 523, 525):
resp = client.get(f"/videos/{job_id}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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 已消费该预算。

@johnnyzhang-eng

Copy link
Copy Markdown
Contributor

我的 #324 也改 sufy.py——抽了个 ChatCompletionsFace 让出图和判官共用建连和重试,和你这版重叠。你把重试整个移到 Gateway 之后那层就多余了,所以不管哪边先合,我都按你的 AdapterResult 收,不另起一套。

@xiaocheny214

Copy link
Copy Markdown
Contributor Author

我的 #324 也改 sufy.py——抽了个 ChatCompletionsFace 让出图和判官共用建连和重试,和你这版重叠。你把重试整个移到 Gateway 之后那层就多余了,所以不管哪边先合,我都按你的 AdapterResult 收,不另起一套。

现按照我的来做吧。咱们把重试的逻辑统一放在gateway做,这样方便后续的链路追踪、熔断、限流等逻辑的引入,以及更换模型路由。这样看起来,重试逻辑也不会太过散乱,你觉得呢?
@johnnyzhang-eng

@johnnyzhang-eng

Copy link
Copy Markdown
Contributor

同意,重试归 Gateway。#324 没有另起一套:它改的是 sufy.py 里已有那处,把措辞从「图像服务」改成通用、让判官复用同一条建连和退避,你这版落地后删的是同一处,不会留两套。另外 #331 自 08-17 是冲突态没再动过而 #324 已绿,所以我按互不阻塞处理,谁先合我跟谁改。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

图/视频调用需要把重试、Fallback 和计费边界从 adapter 里抽出来

2 participants