A retry wrapper
Why it matters Retry logic is a magnet for features: jitter, policies, budgets, circuit breakers. Each is real somewhere. Most call sites need none of them.
A nightly export calls a partner API that sometimes drops the connection. The job runs once a night, on one worker, with nobody else calling the API at that hour. The team wants: retry on ConnectionError or TimeoutError (including their subclasses), waiting 0.5 s, then 1 s, then 2 s (doubling), at most four attempts in all; any other error is a bug and must surface at once.
The wrapper takes the sleep function as an argument, so tests can record waits instead of waiting.
retry(lambda: api.fetch_page(3), time.sleep) # up to 4 attempts
retry(fetch, time.sleep, attempts=3, base=1) # waits 1, 2Write retry(fn, sleep, attempts=4, base=0.5). Call fn() and return its result. If it raises ConnectionError or TimeoutError (or a subclass), call sleep(base * 2 ** k) before retry number k + 1 (so 0.5, 1.0, 2.0 by default) and try again, up to attempts calls in all. If the last attempt fails, raise that error. Any other exception propagates at once, with no retry. Rule: at most 120 syntax nodes (code_size).
Spotted a problem in this lesson? Report it · Ask about this lesson
This exercise opens soon
Finish the lesson before it and this one unlocks. The whole course is free, no account needed, and you can read this lesson right now.
This browser is blocking cookies for learn.floati.life, so lessons you finished here cannot open in order. Allow cookies for this site and reload.