mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-30 01:03:37 +00:00
* fix(feishu): add retry with linear backoff for send rate-limit errors When Feishu returns code 230020 (per-chat rate limit), requestFeishuApi now retries up to 2 times with linear backoff (500ms, 1000ms). The reply path (im.message.reply) is also covered via the same retry helper. Confirmed by a real 20-concurrent-send stress test: all 20 messages succeed after retry. Closes #70879 * ci: retrigger CI * fix(feishu): retry HTTP 429 and code 11232 for message send rate limits Feishu Open API has three send-time rate limit signals: HTTP 429 (gateway-wide quota), business code 11232 (tenant-level message service: 100/min, 5/sec), and 230020 (per-chat). Previously only 230020 was retried; HTTP 429 and 11232 propagated as fatal errors. - Add 11232 to FEISHU_SEND_RATE_LIMIT_CODES. - In getFeishuSendRateLimitCode, recognize HTTP 429 before reading the body code so gateway-level limits enter the retry loop. - Update doc comment listing both gateway and business sources. * test(feishu): add focused retry coverage for 11232 and HTTP 429 The previous send.retry.test.ts only exercised 230020 / 230006 / non-rate codes / plain errors. After expanding the retry policy in90c787096to cover code 11232 (tenant-level message rate limit) and gateway-level HTTP 429, ClawSweeper review #89659 (P2) flagged the tests as no longer matching the production behavior. - getFeishuSendRateLimitCode: assert 11232 returns 11232, HTTP 429 returns 429, and HTTP 429 wins over body code when both are present. - requestFeishuApi: cover 11232 retry-then-success, 429 retry-then-success, exhaustion paths for both, and a mixed 230020 → 11232 → ok recovery. * fix(feishu): retry on fulfilled rate-limit response bodies (no-throw) The Feishu node SDK sometimes resolves a non-throwing response that carries a rate-limit code in its body (e.g. { code: 11232, msg: ... }) instead of rejecting. requestFeishuApi previously returned that body straight away and downstream assertFeishuMessageApiSuccess failed once with no retry — the same shape that issue #28157 fixed earlier on the typing/reaction path via getBackoffCodeFromResponse. ClawSweeper review on #89659 (P1, comment-shared.ts:140) flagged the gap. Mirror the typing-path pattern for the send helper: - Add getFeishuSendRateLimitCodeFromResponse to classify fulfilled bodies against FEISHU_SEND_RATE_LIMIT_CODES (230020, 11232). - In requestFeishuApi, after each fulfilled await, classify before returning. If the body is a retryable rate limit and there are attempts left, continue the loop. After exhaustion, wrap the last fulfilled body into a synthetic AxiosError-shaped error so callers see the same error shape as the throw path. - Add 11 focused tests covering fulfilled 11232/230020 retry-then-ok, exhaustion, mixed throw → fulfilled → ok recovery, and pass-through for code 0 / non-rate-limit codes. * fix(feishu): break loop on final-attempt fulfilled rate-limit body ClawSweeper review ondc8d3be7d(P1, comment-shared.ts:166) caught a real bug: when the final retry attempt also fulfilled with a rate-limit body (e.g. { code: 11232, ... }), the guard `attempt < FEISHU_SEND_MAX_RETRIES` was false so control fell through to `return result` — bypassing the synthetic-error exhaustion path and handing the rate-limit body to the caller as if it were a successful response. The fulfilled-exhaustion test missed this because Vitest's local fs module cache served the pre-fix shape; running with a fresh cache reproduces the failure. Split the fulfilled-rate-limit branch so the body is always captured, then continue on a non-final attempt or break on the final attempt. Breaking falls through to the synthetic AxiosError-shaped throw below, which is exactly what the existing exhaustion test asserts. * fix(feishu): retry on send rate-limit errors 230020/11232/429 (#89659) (thanks @ladygege) --------- Co-authored-by: marshall.m <marshall.m@binance.com> Co-authored-by: sliverp <870080352@qq.com>