Skip to content

:retry_after ignored if there is a Retry-After response header #463

@dmarkow

Description

@dmarkow

The documentation for :retry_delay says:

if not set, which is the default, the retry delay is determined by the value of the Retry-After header on HTTP 429/503 responses. If the header is not set, the default delay follows a simple exponential backoff: 1s, 2s, 4s, 8s, ...

This makes it seem like the priority would be:

  • Use the configured :retry_delay option
  • If not provided, use the Retry-After header
  • If there's no header, use the backoff strategy

But it seems that it's really:

  • If the Retry-After header is present, use it
  • If there's no header, use the :retry_delay option
  • If that's not set, use the backoff strategy

req/lib/req/steps.ex

Lines 2210 to 2238 in ba4de2a

defp get_retry_delay(request, %Req.Response{status: status} = response, retry_count)
when status in [429, 503] do
if delay = Req.Response.get_retry_after(response) do
{request, delay}
else
calculate_retry_delay(request, retry_count)
end
end
defp get_retry_delay(request, _response, retry_count) do
calculate_retry_delay(request, retry_count)
end
defp calculate_retry_delay(request, retry_count) do
case Req.Request.get_option(request, :retry_delay, &exp_backoff/1) do
delay when is_integer(delay) ->
{request, delay}
fun when is_function(fun, 1) ->
case fun.(retry_count) do
delay when is_integer(delay) and delay >= 0 ->
{request, delay}
other ->
raise ArgumentError,
"expected :retry_delay function to return non-negative integer, got: #{inspect(other)}"
end
end
end

I'm unsure if this is a bug and it should always use the :retry_after option if it's set, or if it's a documentation fix to clarify that :retry_after is ignored when there's a Retry-After header.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions