fix: handle Discord typing indicator 429 gracefully
The typing indicator loop (send_typing) ran every 8s and died on any exception, including Discord 429 rate limits. Once a 429 killed the loop, the indicator never restarted — and the raw exception bounce could cascade into broader gateway instability. Changes: - Bump sleep interval from 8s to 12s (typing light lasts ~10s) - On 429: extract retry_after, log a warning, sleep the backoff, and continue the loop - On non-rate-limit errors: log debug and return (unchanged behaviour)
This commit is contained in:
@@ -2706,8 +2706,13 @@ class DiscordAdapter(BasePlatformAdapter):
|
|||||||
|
|
||||||
Discord's TYPING_START gateway event is unreliable in DMs for bots.
|
Discord's TYPING_START gateway event is unreliable in DMs for bots.
|
||||||
Instead, start a background loop that hits the typing endpoint every
|
Instead, start a background loop that hits the typing endpoint every
|
||||||
8 seconds (typing indicator lasts ~10s). The loop is cancelled when
|
12 seconds (typing indicator lasts ~10s). The loop is cancelled when
|
||||||
stop_typing() is called (after the response is sent).
|
stop_typing() is called (after the response is sent).
|
||||||
|
|
||||||
|
Rate-limit handling: if a 429 is encountered, the loop logs a
|
||||||
|
warning, sleeps for the ``retry_after`` duration (or a sensible
|
||||||
|
default), and continues — it does NOT die on a single rate-limit
|
||||||
|
hit. Only CancelledError (from stop_typing) stops the loop.
|
||||||
"""
|
"""
|
||||||
if not self._client:
|
if not self._client:
|
||||||
return
|
return
|
||||||
@@ -2727,9 +2732,22 @@ class DiscordAdapter(BasePlatformAdapter):
|
|||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug("Discord typing indicator failed for %s: %s", chat_id, e)
|
# Don't die on 429 — backoff and continue
|
||||||
return
|
retry_after = self._extract_discord_retry_after(e)
|
||||||
await asyncio.sleep(8)
|
if retry_after is not None:
|
||||||
|
logger.warning(
|
||||||
|
"Typing indicator rate-limited for %s; retrying in %.1fs",
|
||||||
|
chat_id, retry_after,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.debug(
|
||||||
|
"Discord typing indicator failed for %s: %s",
|
||||||
|
chat_id, e,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
await asyncio.sleep(retry_after)
|
||||||
|
continue
|
||||||
|
await asyncio.sleep(12)
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
Reference in New Issue
Block a user