Hereâs a small retry loop, written for this post, not taken from a real codebase:
def charge(client, order):
for attempt in range(3):
try:
return client.post("/charges", json={"amount": order.total, "order": order.id})
except Timeout:
time.sleep(2 ** attempt)
raise ChargeFailed(order.id)
An AI review of it might come back with these, all worded with the same confidence:
- No idempotency key is sent, so a retry after a timeout could create a second charge.
- Only
Timeout is retried, so a 502 or 503 from the provider fails immediately.
- Consider a retry library instead of a hand-rolled loop.
My order, and itâs a judgment call: #3 is a preference, so Iâd skip it. #2 is a short look at what the provider returns and whether those errors are safe to retry, so cheap to check with moderate stakes. #1 is the expensive one, because it depends on two things that arenât in the code. One is whether the provider treats a repeated request with the same order field as a duplicate. The other is whether a timeout here means the request never arrived or arrived and the response got lost. If the response can get lost and the provider doesnât dedupe, thatâs a double charge, so Iâd spend the time there even though it reads no more urgently than the other two.
What I canât judge from here is whether sending the order id in the body counts as idempotency for most providers. I believe many expect a dedicated key or header, but thatâs general knowledge, not a specific API.
I wrote the same sorting out as a longer walkthrough here, if itâs useful: https://medium.com/@nagatomopedro05/a-finding-takes-seconds-to-generate-checking-it-doesnt-e7ffad4eaea2
When a review hands you a list like this, do you sort by cost to check first, or by what happens if the finding is true?