You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
摘要
企业/自建 LLM 网关带流控(429 +
Retry-After)时,dsh 触发限流后不会自动恢复:dsh-llm-retry的normal重试模式在providerRetryAfterMs > policy.maxDelayMs(默认 10s)时直接return next()放弃(lib/index.jsL146-147),错误原样上抛、turn 终止——用户看到的就是"卡在那里,不自动恢复"(#891)。对比 claude code/zcode 会等待 Retry-After 窗口后再重试。企业网关的流控窗口(30-60s 常见)几乎必然超过 10s 上限,因此该缺陷在流控网关上是确定性必现。复现步骤
Retry-After: 30(或任何 >10 的值)的网关(企业流控网关常见行为)。根因(源码定位,rc.6)
@deepseek-ai/dsh-llm-retry/lib/index.jsrecover()(L129-152):dsh-llmL356-366):maxRetries=2、initialDelayMs=500、maxDelayMs=1e4(10s)。Retry-After并携带(dsh-llm-deepseekL601-606)——丢失发生在重试决策层:normal 模式下 Retry-After 大于本地退避上限即视为"不可等",直接放弃。maxDelayMs是本地退避的上限,却被用来否决服务端明确告知的重试时间——网关自己知道何时恢复,dsh 却拒绝等它。建议修复
方案 A(推荐)· 允许等待服务端 Retry-After,另设绝对上限:normal 模式下
providerRetryAfterMs > maxDelayMs不再直接放弃,而是按providerRetryAfterMs等待(受新的独立绝对上限约束,如
maxProviderRetryAfterMs默认 5 分钟):maxDelayMs继续约束本地指数退避;服务端 Retry-After 走自己的上限。一处修复恢复企业流控网关的自动恢复能力。
方案 B · 配置面:允许部署方单独配置
retryAfterCapMs(或提高maxDelayMs),并保持"超过上限时明确提示"——至少给出可执行的配置建议而非静默放弃。
方案 C(日志):放弃时记录明确原因
("gateway asked to retry after ${n}s but maxDelayMs=${m}s — raise maxDelayMs"),
当前静默
return next()让用户无从得知为何不重试。影响
不自动恢复,需人工重发(触发429限流后不会自动恢复 #891;claude code/zcode 同场景可自动恢复)
环境
dsh-llm-retry/lib/index.jsL129-152、dsh-llmL356-366、dsh-llm-deepseekL601-606;Node v24.16.0,Windows 11)验证材料
return next()分支、L138 的 RATE_LIMIT 放行、L601-606 的 Retry-After 携带(证明信息在、决策层丢弃)
差异仅在阈值比较
Retry-After: 30的 429 网关即可观察"不等待、直接失败"First source-located analysis of discussion #891. Happy to open a PR with fix option A.
All reactions