Fix the backoff schedule for a retry wrapper

Review the AI's codeMedium15 min

Your task

Your service wraps an idempotent remote call in a retry helper with exponential backoff. The first version slept after the last failed attempt, then returned null instead of the error, and it retried every kind of error. The new version first works out the list of sleeps a call goes through, so the policy can be tested without a clock.

An assistant wrote retry_sleep_schedule(outcomes, max_attempts, base_delay_ms, cap_delay_ms). It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • outcomes: what each attempt returns, in order: "ok", "retryable" or any other string, such as "terminal" or "auth_error".
  • max_attempts: the most attempts allowed.
  • base_delay_ms: the first sleep, in milliseconds.
  • cap_delay_ms: the longest sleep allowed.
  • Return the sleeps, in milliseconds, in the order they happen.

Rules the tests check:

  • If max_attempts is below 1, return [].
  • The ceiling is cap_delay_ms, or 3600000 (one hour) when cap_delay_ms is 0 or less.
  • The first delay is base_delay_ms, or 0 if that is negative, and never more than the ceiling. Each later delay is double the one before, and never more than the ceiling.
  • Attempt k, counting from 1, has the outcome outcomes[k - 1]. Past the end of the list, every attempt is "retryable".
  • After each attempt, in this order:
    1. "ok": stop.
    2. Anything other than "retryable": stop. Such errors are not worth retrying.
    3. It was attempt number max_attempts: stop. The caller gets the last error now, with no sleep.
    4. Otherwise sleep for the current delay, then try again.

Examples

retry_sleep_schedule(outcomes: list[str], max_attempts: int, base_delay_ms: int, cap_delay_ms: int) -> list[int]
Example 1
Inputretry_sleep_schedule(["retryable", "retryable", "ok"], 5, 1000, 8000)
Output[1000, 2000]
Example 2
Inputretry_sleep_schedule(["retryable", "terminal"], 5, 1000, 8000)
Output[1000]
Example 3
Inputretry_sleep_schedule(["retryable", "retryable", "retryable"], 3, 100, 10000)
Output[100, 200]