~/problems / Simulation & OOP design / Object-oriented design and extensible simulations

OA: Retriable function

medium 3 levels ~45 min Airbnb

Level 1 Retry a failing call

Network calls and database queries fail now and then for reasons that go away by themselves. Build a reusable retry helper, Retrier, that re-runs a function until it succeeds or runs out of attempts.

Retrier(max_attempts: int, delay: float = 0, sleep=None)
  • max_attempts is the total number of calls allowed (the first try counts). If it is less than 1, the constructor raises ValueError.
  • delay is how long to wait between attempts, in seconds.
  • sleep is the function used to wait; None means time.sleep. The tests pass a fake that only records the waits, so never wait any other way.

Methods:

  • call(fn, *args, **kwargs): call fn(*args, **kwargs). If it returns, return its result right away. If it raises an exception, wait delay with sleep(delay) and try again, up to max_attempts calls in total. There is no wait after the last failed attempt. If every attempt fails, re-raise the last exception (the same exception object).
  • last_attempts (an attribute or property): how many times fn was called during the most recent call, whether it succeeded or not; 0 before the first call.

A Retrier can be reused for many calls; each call starts fresh.

waits = []
r = Retrier(max_attempts=4, delay=0.5, sleep=waits.append)

calls = iter([ConnectionError("down"), ConnectionError("down"), "ok"])
def flaky():
    x = next(calls)
    if isinstance(x, Exception):
        raise x
    return x

r.call(flaky)       # "ok"
waits               # [0.5, 0.5]
r.last_attempts     # 3

r.call(int, "12")   # 12   (arguments are passed through)
r.last_attempts     # 1
Show hint

loop over the attempts and remember the last exception. There's no point sleeping after the final attempt.

Level 2 unlocks when level 1 passes.

Level 3 unlocks when level 2 passes.

Topic: Object-oriented design and extensible simulations. Classes that survive new requirements: games, payments, subscriptions, refactors.

0:00
Ctrl ' run · Ctrl ↵ submit
esc