MessageWeave/src
anonsaber f4cae00adc telegram: 重试之间加指数退避,429 尊重服务端 retry_after(01a0e75f-f7e3)
现状:send_text 的 for _ in 0..=max_retries 重试循环在两次尝试之间零延迟,
任何 5xx/超时/429 都以最短间隔连续打 API,429 场景下反而更容易触发二次限流。

改动(ROADMAP 缺口②「Telegram 429 退避」):
- backoff_delay_ms(attempt: u8) 纯函数:起步 250ms、每轮 x2、单轮封顶 4s。
  调用方 sleep 只走这一个出口,便于单测直接断言序列而无需真实等待。
- retry_after_ms(body) 纯函数:解析 429 响应体 parameters.retry_after(秒),
  转毫秒后钳到 60s 上限;缺字段/非数字/非正/非有限值一律回退到指数退避。
- 总退避预算上限 60s:耗尽后 delay 归零不再 sleep,避免单次 send_text 长时间挂起。
- 429 单独分支,错误串改为 telegram request rate limited (429) 以便区分限流与一般失败。

语义不变:max_retries 仍 cap 5、每次请求仍受 telegram_timeout_ms 约束、
返回 Result<(), String>、错误串不泄漏 token。

测试:client() 通过 with_sleep_override 注入 no-op sleep,退避逻辑完整走通但不真实等待。
新增 3 个测试:429 端到端(mock 返回 parameters.retry_after=1,断言 2..=3 次请求)、
backoff 序列(250/500/1000/2000/4000 后封顶)、retry_after 解析与钳制。
GATE-P0 全绿:fmt --check、check --locked、clippy --locked --all-targets -D warnings、
test --locked → 52 passed / 0 failed / 1 ignored。
2026-09-28 18:13:08 +08:00
..
domain fix(notify): /ready JMAP 探针对齐真实客户端(Basic 认证 + 路径归一) 2026-09-28 10:37:22 +08:00
ai.rs feat: initial MessageWeave release 2026-09-25 09:14:04 +08:00
channel.rs telegram: 重试之间加指数退避,429 尊重服务端 retry_after(01a0e75f-f7e3) 2026-09-28 18:13:08 +08:00
config.rs fix(worker,state,jmap,config): close independent-review findings 2026-09-27 12:53:05 +08:00
debug.rs debug: 新增 /debug/* 远程联调面,双因子门禁默认绝对关闭(01a0e319) 2026-09-28 15:00:49 +08:00
domain.rs feat: initial MessageWeave release 2026-09-25 09:14:04 +08:00
error.rs feat: initial MessageWeave release 2026-09-25 09:14:04 +08:00
main.rs debug: 新增 /debug/* 远程联调面,双因子门禁默认绝对关闭(01a0e319) 2026-09-28 15:00:49 +08:00
notify.rs debug: 新增 /debug/* 远程联调面,双因子门禁默认绝对关闭(01a0e319) 2026-09-28 15:00:49 +08:00
state.rs fix(worker,state,jmap,config): close independent-review findings 2026-09-27 12:53:05 +08:00
web.rs feat: initial MessageWeave release 2026-09-25 09:14:04 +08:00
worker.rs fix(worker,state,jmap,config): close independent-review findings 2026-09-27 12:53:05 +08:00