Retry a function with exponential backoff and jitter
Coding, Medium
Small real code that works when called late, twice, or with bad input.
Write retry(fn, options) in JavaScript (or the same idea in another language). fn is an async function that may fail. retry calls fn, and if it throws, waits and calls it again, up to retries more times (so at most 1 + retries calls). The wait before retry number k (k = 1, 2, ...) is a random time between 0 and min(maxMs, baseMs * 2^(k-1)). When fn succeeds, return its result. When all calls fail, throw the error of the last call. The options are retries (default 3), baseMs (default 100), maxMs (default 5000) and shouldRetry(error) (default: retry every error; if it returns false, stop at once and throw that error). Your function must be easy to test without real waiting: the options also include sleep(ms) (default: a real timer) and random() (default: Math.random), which a test can replace.
Examples
Constraints
retriesis a whole number >= 0. Refuse any other value with a clear error.retries = 0means one call and no wait.fncan also throw before it returns a promise (a normal function). Treat that as a failure too.- The code must not use real time in tests: let the caller pass in the sleep function and the random function.
- No wait after the last failed call.
Your answer must contain
- The code
- How the wait grows, how the cap and the jitter apply, and why jitter is there
- What you do for errors that should not be retried, and what the caller sees at the end
- How you would test it without waiting in real time