fix(discord): retry 429s in the standalone send path, honoring retry_after - #44488
fix(discord): retry 429s in the standalone send path, honoring retry_after#44488AIalliAI wants to merge 1 commit into
Conversation
|
Verified the Discord standalone 429 retry implementation — clean, well-structured. What I checked:
Test coverage (5 tests): 429→success, persistent 429 exhaustion, huge retry_after gives up, non-429 not retried, no retry_after → backoff. Covers the key paths. Parity with the Telegram retry helper in |
|
Requesting maintainer review — this is ready to land from my side. Standalone fork CI is pending first-run approval here; the rollup branch in #44061 carrying this session's batch is fully green on upstream CI (all test shards, typecheck, e2e). |
8c47c45 to
7010406
Compare
…after The standalone REST send path (used by send_message_tool when no live gateway runner is in-process) treated a 429 like any other non-2xx: it read the body and returned an error immediately, so a transient rate limit dropped the message instead of backing off. Discord reports a precise retry_after on these responses, which the path ignored. - add a bounded _standalone_post_with_retry wrapper (3 attempts) that honors retry_after from the JSON body first, then the Retry-After / X-RateLimit-Reset-After headers, falling back to exponential backoff - cap the wait at 10s so a long-lived/global limit gives up instead of stalling a blocking CLI/tool call - route the text, forum-thread, and forum-multipart sends through the wrapper, rebuilding the FormData per attempt since aiohttp bodies can't be re-sent - read every response through the existing bounded json/text limiters so the retry path keeps main's oversized-body protection Fixes NousResearch#44468
7010406 to
80c971f
Compare
|
Thanks for the focused Discord delivery fix. The premise is present on current main: the standalone text POST returns immediately for every non-2xx status at The PR base is an ancestor of current Automated hermes-sweeper review. |
|
Discord Feature Parity & Alignment Campaign interlock: tracked by EPIC #79564. Original contributor lane; preservation and integration routing remain explicit in the campaign ledger. |
Summary
Fixes #44468 —
hermes send --to discord:...dropped all remaining chunks of a multi-chunk message when one chunk hit a 429, because the standalone REST path (plugins/platforms/discord/adapter.py::_standalone_send) converted any 429 straight into an error dict with no retry, and the Discord chunk loop intools/send_message_tool.pyreturns on the first error.This adds
_standalone_post_with_retryto the Discord plugin and applies it to the standalone text-message POST and both forum thread-creation POSTs:_send_telegram_message_with_retry).retry_after: parsed from the 429 JSON body first (Discord reports sub-second precision there, e.g. theretry_after: 0.3from the issue), falling back to theRetry-After/X-RateLimit-Reset-Afterheaders, then to exponential backoff (1s, 2s) when neither parses.retry_afterabove 10s (long/global rate limit) fails fast instead of stalling the blocking CLI/tool call.FormDatacannot be sent twice.With retry inside
_standalone_send, the chunk loop insend_message_tool.pyneeds no change: a transient 429 on chunk N now retries and succeeds, and the remaining chunks proceed — parity with the Telegram path, which retries inside_send_telegram. (The per-media upload loop is left as-is: its failures are already non-fatal warnings that don't drop subsequent sends, and wrapping it would change its streaming-from-disk memory profile.)Tests
New
TestSendDiscord429Retryintests/tools/test_send_message_tool.py:retry_after(0.3s), send succeeds, 2 POSTsretry_after: 3600→ fails fast, no sleep, 1 POSTtests/tools/test_send_message_tool.py: 138 passed (35 Discord-related, 5 new).