The before code retries immediately on failure, causing potential overload. The after code waits longer between retries, doubling the delay each time up to a max, reducing retry frequency and giving the service time to recover.
import time
import random
# Before: naive retry without backoff
def call_service_naive():
for _ in range(5):
try:
# simulate service call
result = unreliable_service()
return result
except Exception:
pass # immediately retry
raise Exception("Failed after retries")
# After: retry with exponential backoff
def call_service_backoff():
max_retries = 5
delay = 0.5 # initial delay in seconds
max_delay = 8
for attempt in range(max_retries):
try:
result = unreliable_service()
return result
except Exception:
if attempt == max_retries - 1:
break
sleep_time = delay * (2 ** attempt)
sleep_time = min(sleep_time, max_delay)
time.sleep(sleep_time)
raise Exception("Failed after retries with backoff")
# Simulated unreliable service
def unreliable_service():
if random.random() < 0.7:
raise Exception("Temporary failure")
return "Success"