fix(telegram): backoff for transient network errors in sendChatAction#55838
fix(telegram): backoff for transient network errors in sendChatAction#55838sumaiazaman wants to merge 2 commits into
Conversation
Greptile SummaryThis PR extends the existing
Confidence Score: 5/5Safe to merge — logic is correct and well-tested; remaining findings are P2 style improvements. All findings are P2 (broad substring match, missing max in log message). No correctness, data-integrity, or reliability issues found. The dual-counter backoff logic is sound and all new behaviour is covered by tests. sendchataction-401-backoff.ts — minor: tighten the 'network request' substring predicate and restore the N/max indicator in the backoff log.
|
| Filename | Overview |
|---|---|
| extensions/telegram/src/sendchataction-401-backoff.ts | Adds transient network error detection and a second consecutive-failure counter integrated into the shared backoff path. Two minor style concerns: broad 'network request' substring and missing N/max in backoff log. |
| extensions/telegram/src/sendchataction-401-backoff.test.ts | Adds four new test cases covering transient error swallowing, backoff triggering, suspension, and counter reset on success. Existing tests updated correctly. |
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/telegram/src/sendchataction-401-backoff.ts
Line: 72
Comment:
**Overly broad "network request" substring match**
`lower.includes("network request")` is a very generic fragment. An API error like `"network request returned status 500"` or `"rate-limited: too many network requests"` would match this predicate and be silently swallowed as a transient error. The other patterns (`econnreset`, `etimedout`, `fetch failed`, `socket hang up`) are specific low-level I/O error codes, but this one could absorb HTTP-level failures from Telegram's API itself.
Consider tightening the match to the actual Node.js fetch/undici error message format:
```suggestion
lower.includes("network request for") ||
```
This still catches the documented Telegram bot SDK pattern (`"Network request for 'sendChatAction' failed!"`) without matching unrelated strings containing "network request".
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: extensions/telegram/src/sendchataction-401-backoff.ts
Line: 119-121
Comment:
**Backoff log no longer shows suspension threshold**
The previous message included `(failure ${consecutive401Failures}/${maxConsecutive401})`, giving operators an at-a-glance view of how many more failures remain before suspension. The new unified message `(failure ${totalFailures})` drops the max, which makes it harder to triage a stream of 401 backoff logs in production.
Consider restoring context-sensitive max information:
```suggestion
logger(
`sendChatAction backoff: waiting ${backoffMs}ms before retry ` +
`(failure ${totalFailures}/${consecutive401Failures > 0 ? maxConsecutive401 : maxConsecutiveTransient})`,
);
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(telegram): add backoff for transient..." | Re-trigger Greptile
| const message = error instanceof Error ? error.message : JSON.stringify(error); | ||
| const lower = message.toLowerCase(); | ||
| return ( | ||
| lower.includes("network request") || |
There was a problem hiding this comment.
Overly broad "network request" substring match
lower.includes("network request") is a very generic fragment. An API error like "network request returned status 500" or "rate-limited: too many network requests" would match this predicate and be silently swallowed as a transient error. The other patterns (econnreset, etimedout, fetch failed, socket hang up) are specific low-level I/O error codes, but this one could absorb HTTP-level failures from Telegram's API itself.
Consider tightening the match to the actual Node.js fetch/undici error message format:
| lower.includes("network request") || | |
| lower.includes("network request for") || |
This still catches the documented Telegram bot SDK pattern ("Network request for 'sendChatAction' failed!") without matching unrelated strings containing "network request".
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/telegram/src/sendchataction-401-backoff.ts
Line: 72
Comment:
**Overly broad "network request" substring match**
`lower.includes("network request")` is a very generic fragment. An API error like `"network request returned status 500"` or `"rate-limited: too many network requests"` would match this predicate and be silently swallowed as a transient error. The other patterns (`econnreset`, `etimedout`, `fetch failed`, `socket hang up`) are specific low-level I/O error codes, but this one could absorb HTTP-level failures from Telegram's API itself.
Consider tightening the match to the actual Node.js fetch/undici error message format:
```suggestion
lower.includes("network request for") ||
```
This still catches the documented Telegram bot SDK pattern (`"Network request for 'sendChatAction' failed!"`) without matching unrelated strings containing "network request".
How can I resolve this? If you propose a fix, please make it concise.| `sendChatAction backoff: waiting ${backoffMs}ms before retry ` + | ||
| `(failure ${consecutive401Failures}/${maxConsecutive401})`, | ||
| `(failure ${totalFailures})`, | ||
| ); |
There was a problem hiding this comment.
Backoff log no longer shows suspension threshold
The previous message included (failure ${consecutive401Failures}/${maxConsecutive401}), giving operators an at-a-glance view of how many more failures remain before suspension. The new unified message (failure ${totalFailures}) drops the max, which makes it harder to triage a stream of 401 backoff logs in production.
Consider restoring context-sensitive max information:
| `sendChatAction backoff: waiting ${backoffMs}ms before retry ` + | |
| `(failure ${consecutive401Failures}/${maxConsecutive401})`, | |
| `(failure ${totalFailures})`, | |
| ); | |
| logger( | |
| `sendChatAction backoff: waiting ${backoffMs}ms before retry ` + | |
| `(failure ${totalFailures}/${consecutive401Failures > 0 ? maxConsecutive401 : maxConsecutiveTransient})`, | |
| ); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/telegram/src/sendchataction-401-backoff.ts
Line: 119-121
Comment:
**Backoff log no longer shows suspension threshold**
The previous message included `(failure ${consecutive401Failures}/${maxConsecutive401})`, giving operators an at-a-glance view of how many more failures remain before suspension. The new unified message `(failure ${totalFailures})` drops the max, which makes it harder to triage a stream of 401 backoff logs in production.
Consider restoring context-sensitive max information:
```suggestion
logger(
`sendChatAction backoff: waiting ${backoffMs}ms before retry ` +
`(failure ${totalFailures}/${consecutive401Failures > 0 ? maxConsecutive401 : maxConsecutiveTransient})`,
);
```
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: 89bb289a19
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // Swallow transient errors — sendChatAction is best-effort | ||
| return; | ||
| } | ||
| throw error; | ||
| } |
There was a problem hiding this comment.
Reset transient counter on non-transient errors
The new maxConsecutiveTransient logic only clears consecutiveTransientFailures on success or a 401, but not when another non-transient error is thrown. This means transient failures are treated as "consecutive" across intervening 5xx/other errors, so a sequence like transient → 500 → transient can still hit suspension even though the network failures were not consecutive. That can incorrectly suspend sendChatAction and apply backoff based on stale transient state.
Useful? React with 👍 / 👎.
|
Resolved both review findings:
See commit f8de59f. |
|
Closing this as duplicate or superseded after Codex automated review. Close PR #55838 as superseded. Current main no longer matches the original retry-spam failure mode because Telegram typing goes through the shared typing lifecycle and stops the keepalive loop after consecutive start failures. The narrower handler-level transient cooldown work is now tracked by the newer open PR #55886, which came from the #55811 discussion and covers the same Telegram sendChatAction surface with review follow-ups. Best possible solution: Close #55838 as superseded, keep the shipped shared typing breaker behavior on main, and route any remaining Telegram sendChatAction transient cooldown work through the newer canonical PR #55886. What I checked:
So I’m closing this here and keeping the remaining discussion on the canonical linked item. Codex Review notes: model gpt-5.5, reasoning high; reviewed against 7e376e5aba32. |
Summary
sendChatActionhandlermaxConsecutiveTransient)Closes #55811
Test plan
pnpm checkpasses