Capped exponential backoff retry in Elixir

Elixir
defmodule RetryBackoff do
  @max_attempts 5
  @base_ms 100
  @cap_ms 5_000

  def run(fun, attempt \\ 1) do
    try do
      fun.()
    rescue
      error ->
        if attempt >= @max_attempts, do: reraise(error, __STACKTRACE__)
        delay = min(@base_ms * Integer.pow(2, attempt - 1), @cap_ms)
        jitter = :rand.uniform(div(delay, 2) + 1)
        Process.sleep(min(delay + jitter, @cap_ms))
        run(fun, attempt + 1)
    end
  end
end