tenacity icon indicating copy to clipboard operation
tenacity copied to clipboard

Is it possible to specify retry-dependent wait?

Open FeiYao-Edinburgh opened this issue 2 years ago • 1 comments

Hi there,

I find that wait_exponential is suitable for balancing retries against latency when a required resource is unavailable for an unknown duration, while wait_random_exponential is suitable for resolving contention between multiple processes for a shared resource. So is it possible to specify wait according to retry. For instance, if retry_if_exception_type(requests.exceptions.HTTPError), do wait_exponential, while for retry_if_exception_type(urllib3.exceptions.ProtocolError), do wait_random_exponential?

Thanks, Fei

FeiYao-Edinburgh avatar Jan 18 '23 15:01 FeiYao-Edinburgh

You could have two separate decorators with different retry_if_exception_type for that:

import tenacity

key_retry = tenacity.retry(
    stop=tenacity.stop_after_attempt(3),
    retry=tenacity.retry_if_exception_type(KeyError),
    reraise=True,
)
value_retry = tenacity.retry(
    stop=tenacity.stop_after_attempt(2),
    retry=tenacity.retry_if_exception_type(ValueError),
    reraise=True,
)

@key_retry
@value_retry
def callit(thing):
    value = thing()
    print("got value", value)

Then you'd get:

from unittest import mock
logging.basicConfig(level=logging.INFO)

try:
    callit(mock.MagicMock(side_effect=[ValueError(), "success 1"])) 
    callit(mock.MagicMock(side_effect=[ValueError(), ValueError(), "success 2"]))
except Exception as exc:
    print("got exception", repr(exc))

result:

got value success 1
got exception ValueError()

and

try:
    callit(mock.MagicMock(side_effect=[KeyError(), "success 1"])) 
    callit(mock.MagicMock(side_effect=[KeyError(), KeyError(), "success 2"]))
    callit(mock.MagicMock(side_effect=[KeyError(), KeyError(), KeyError(), "success 3"]))
except Exception as exc:
    print("got exception", repr(exc))

resulting in

got value success 1
got value success 2
got exception KeyError()

In this example, I changed the stop conditions because that's easier to demonstrate, but you could use this to have different wait functions, different logs, and more.

moshez avatar Mar 28 '23 20:03 moshez