fix(discord): retry chunk delivery#33226
Conversation
Greptile SummaryThis PR improves Discord chunk delivery reliability by pre-resolving channel ID and However, the implementation introduces two logic issues that should be addressed:
Confidence Score: 3/5
Last reviewed commit: badf91c |
| if (params.channelId && params.request && params.rest) { | ||
| await sendWithRetry( | ||
| () => sendDiscordText(params.rest, params.channelId, text, params.replyTo, params.request), | ||
| params.retryConfig, | ||
| ); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Nested retry loops can multiply attempts beyond configured limits
When using the fast path (channelId && request && rest), sendDiscordText is wrapped in sendWithRetry, but sendDiscordText also internally uses the request RetryRunner (created via createDiscordRetryRunner) to wrap each rest.post() call. The inner request runner retries on RateLimitError (status 429), and when it exhausts its attempts and throws, the outer sendWithRetry sees a 429-status error and retries the entire sendDiscordText call again.
With defaults of 3 attempts each, a persistent 429 could result in 3 × 3 = 9 total REST calls to Discord, rather than the intended 3. This violates the account-level retry config and can cause unexpectedly long delivery delays.
Since sendDiscordText already handles chunking internally and accepts a request runner for retrying at the REST-call level, consider either:
- Dropping the outer
sendWithRetryon the fast path (sincerequestalready retries) - Or stripping the inner
requestrunner and relying solely on the outersendWithRetry
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/discord/monitor/reply-delivery.ts
Line: 169-175
Comment:
Nested retry loops can multiply attempts beyond configured limits
When using the fast path (`channelId && request && rest`), `sendDiscordText` is wrapped in `sendWithRetry`, but `sendDiscordText` also internally uses the `request` `RetryRunner` (created via `createDiscordRetryRunner`) to wrap each `rest.post()` call. The inner `request` runner retries on `RateLimitError` (status 429), and when it exhausts its attempts and throws, the outer `sendWithRetry` sees a 429-status error and retries the entire `sendDiscordText` call again.
With defaults of 3 attempts each, a persistent 429 could result in `3 × 3 = 9` total REST calls to Discord, rather than the intended 3. This violates the account-level retry config and can cause unexpectedly long delivery delays.
Since `sendDiscordText` already handles chunking internally and accepts a `request` runner for retrying at the REST-call level, consider either:
- Dropping the outer `sendWithRetry` on the fast path (since `request` already retries)
- Or stripping the inner `request` runner and relying solely on the outer `sendWithRetry`
How can I resolve this? If you propose a fix, please make it concise.
Additional Comments (1)
Prompt To Fix With AIThis is a comment left during a code review.
Path: src/discord/monitor/reply-delivery.ts
Line: 349-357
Comment:
Primary media send missing retry coverage
`sendAdditionalDiscordMedia` (subsequent media items) is now wrapped in `sendWithRetry` via the updated helper, but this primary (first) media attachment send is not. A transient 429 or 5xx here will fail immediately without retrying, while the same error on subsequent attachments would be retried. For consistency, this call should also be wrapped in `sendWithRetry(…, params.retryConfig)`.
How can I resolve this? If you propose a fix, please make it concise. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: badf91cc47
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (params.channelId && params.request && params.rest) { | ||
| await sendWithRetry( | ||
| () => sendDiscordText(params.rest, params.channelId, text, params.replyTo, params.request), | ||
| params.retryConfig, | ||
| ); |
There was a problem hiding this comment.
Preserve outbound activity tracking on direct chunk sends
This fast-path returns after sendDiscordText when rest and a channelId are present, bypassing sendMessageDiscord, which is currently where Discord outbound activity is recorded. In the monitor flow (which passes rest and channel targets), text-only replies will no longer update lastOutboundAt, so channel status endpoints can report stale outbound health despite successful sends. Please record outbound activity in this branch or route through a shared sender that preserves that side effect.
Useful? React with 👍 / 👎.
badf91c to
e847319
Compare
|
Landed via temp rebase onto main.
Thanks @thewilloftheshadow! |
Summary
Describe the problem and fix in 2–5 bullets:
sendDiscordTextwhen possible, and add retry handling for 429/5xx using account-level retry config.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
Discord chunked message delivery now retries on 429/5xx errors (using account retry config) and preserves chunk ordering when using a REST client.
Security Impact (required)
Yes, explain risk + mitigation: N/ARepro + Verification
Environment
Steps
Expected
Actual
Evidence
Attach at least one:
Human Verification (required)
What you personally verified (not just CI), and how:
Compatibility / Migration
Failure Recovery (if this breaks)
src/discord/monitor/reply-delivery.ts,src/discord/monitor/reply-delivery.test.ts.Risks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write
None.