Skip to content

Retry in recursive context is broken since 8.3.0 #478

@sashaCher

Description

@sashaCher

Hello
We observed breaking change in @retry decorator behavior after upgrading the library from 8.2.3 to 8.3.0/8.4.1 version.

Assuming the next code sample (simplified and adjusted to illustrate the exact use-case):

from tenacity import RetryCallState, retry

MAX_RETRY_FIX_ATTEMPTS = 2


def do_retry(retry_state: RetryCallState):
    ex = retry_state.outcome.exception()
    _subject_: str = retry_state.args[0]

    if _subject_ == 'Fix':  # no retry on fix failure
        return False

    if retry_state.attempt_number >= MAX_RETRY_FIX_ATTEMPTS:
        return False

    if ex:
        do_fix_work()
        return True

    return False


@retry(reraise=True, retry=do_retry)
def _do_work(subject: str):
    if subject == 'Error':
        print(f'{subject} is not working')
        raise Exception(f'{subject} is not working')
    print(f'{subject} is working')


def do_any_work(subject: str):
    _do_work(subject)


def do_fix_work():
    _do_work('Fix')


if __name__ == '__main__':
    do_any_work('Error')

In version 8.2.3 it worked correctly means do_any_work function was called twice with do_fix_work in the middle and produced the next output:

Error is not working
Fix is working
Error is not working
Traceback (most recent call last):
...call-stack...
Exception: Error is not working

After upgrading to 8.3.0 or 8.4.1 the code is not working the same way.
There's no additional call of do_any_work after do_fix_work and the code does not end with error:

Error is not working
Fix is working

Process finished with exit code 0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions