Skip to content

Conversation

@Bibo-Joshi
Copy link
Member

When ready, Closes #4966
Will need to dig out my linux machine to write tests

@Bibo-Joshi Bibo-Joshi added the 🔌 bug pr description: bug label Sep 24, 2025
@Bibo-Joshi Bibo-Joshi marked this pull request as ready for review September 24, 2025 20:00
@Bibo-Joshi Bibo-Joshi requested review from aelkheir, Copilot and harshil21 and removed request for aelkheir, Copilot and harshil21 September 24, 2025 20:00
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Fixes infinite loop behavior when bootstrap_retries=-1 is set in Application.run_* and Updater.start_* methods by properly implementing retry termination conditions.

  • Replaces self.running condition with success tracking for webhook operations
  • Adds is_running parameter to application bootstrap initialization
  • Includes comprehensive tests for both polling and webhook scenarios

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/telegram/ext/_updater.py Implements success tracking for webhook delete/set operations to prevent infinite retries
src/telegram/ext/_application.py Adds proper termination condition for application initialization retries
tests/ext/test_updater.py Adds test coverage for infinite bootstrap retries in updater methods
tests/ext/test_application.py Adds test coverage for infinite bootstrap retries in application run methods
changes/unreleased/4973.PtSpAPsm7wh4PWc4p3uajX.toml Documents the bugfix in changelog

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Member

@aelkheir aelkheir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't looked at tests yet. while current approach solves the issue, i am wondering if there would be an issue when breaking the loop from within, i.e without the reliance on network_retry_loop.is_running to track success.

Changing this:

while effective_is_running():
try:
await do_action()
if not infinite_loop:
_LOGGER.debug("%s Action succeeded. Stopping loop.", log_prefix)
break

to:

    while effective_is_running():
        try:
            await do_action()
            _LOGGER.debug("%s Action succeeded. Stopping loop.", log_prefix)
            break

edit:
oh that might break polling i guess

@Bibo-Joshi
Copy link
Member Author

oh that might break polling i guess

yup :D

Checking the return value would also basically bring us back to before #4880 😅
One could argue that this PR now just moves the return True/False from before #4880 into the is_running, but IMHO it's at least still a cleaner interface. An alternative would be to make the infinite_loop variable introduced in #4880 a parameter - get_updates would set it to True, all others to False, such that the first successfull call exits. This as actually the initial draft of #4880 😆 65e6cc9

@aelkheir
Copy link
Member

aelkheir commented Sep 26, 2025

I am a bit late to those discussions :) but here goes

I agree current approach is cleaner than the old return True/False to determine retry logic in that its more explicit

However it's still way inferior to infinite_loop parameter introduced (& removed) in #4880. It would be much nicer to just pass a boolean that determines whether or not the action callback is an long living one (it can have a default value of False since polling is the only place where its True)

future me: i realize i say (long living action callback) a lot below. i mean an action callback that should be re-called even if first attempts are successful.

That would be nicer, simpler than to assume every action callback is a long living one and require the caller to write custom logic in the form of lambdas to terminate the action.

Now according to the discussion at comment #4880, i believe it was removed because it was thought redundant (infinite_loop(=True) and max_retries=(-1) meaning the same thing)
I don't think that's the case, tho the infinite_loop name might give that impression. but

  • infinite_loop(=True) and max_retries=(-1): this action callback is a long living one, execute it indefinitely. e.g polling
  • infinite_loop(=False) and max_retries=(-1): this action callback is not a long living one. if failed, retry it indefinitely. e.g bootstrap initialize when passing app.run_polling(bootstrap_retries=-1)

Yes it might not make sense passing infinite_loop(=True) and max_retries > 0, but i see initial commits of #4880 did handle that case. Even if left unhandled, the logic can still hold: the action call back is long living, execute it 6 times (e.g. poll for one hour with interval 10 seconds) ('')

Last note regarding #4871, i don't see an issue in incrementing retries count regardless of the success state of action_cb. Unless we want to support a use case like ('') and separate between retries because of errors, and normal operation (infinite_loop=True) retries.

@Bibo-Joshi
Copy link
Member Author

Let me re-add the infinite_loop parameter, then :) Maybe a different name though - repeat_on_success? A use case for retry_on_success(=True) and max_retries > 0 (i.e. calling exactly a finite number of times) should still not be needed IMO, so I'll skip that

@Bibo-Joshi Bibo-Joshi merged commit 4bc2f1f into master Sep 27, 2025
29 of 32 checks passed
@Bibo-Joshi Bibo-Joshi deleted the infinite-retry-bootstrap branch September 27, 2025 12:40
@github-actions github-actions bot locked and limited conversation to collaborators Oct 5, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

🔌 bug pr description: bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

starting the bot with bootstrap_retries -1 fails startup

3 participants