Skip to content

Instantly share code, notes, and snippets.

@sescobb27
Created March 22, 2018 20:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sescobb27/a0bf2f2500ee69faf963802e272ae60d to your computer and use it in GitHub Desktop.
Save sescobb27/a0bf2f2500ee69faf963802e272ae60d to your computer and use it in GitHub Desktop.
defmodule ReqWithBackoff do
# hakney :connect_timeout - timeout used when establishing a connection, in milliseconds
# hakney :recv_timeout - timeout used when receiving from a connection, in milliseconds
# poison :timeout - timeout to establish a connection, in milliseconds
# :backoff_max - maximum backoff time, in milliseconds
# :backoff_factor - a backoff factor to apply between attempts, in milliseconds
defp fetch(uri) do
options = [
follow_redirect: true,
recv_timeout: Application.get_env(:arc, :recv_timeout, 5_000),
connect_timeout: Application.get_env(:arc, :connect_timeout, 10_000),
timeout: Application.get_env(:arc, :timeout, 10_000),
max_retries: Application.get_env(:arc, :max_retries, 3),
backoff_factor: Application.get_env(:arc, :backoff_factor, 1000),
backoff_max: Application.get_env(:arc, :backoff_max, 30_000),
]
request(uri, options)
end
defp request(uri, options, tries \\ 0) do
case HTTPoison.get(uri, [], options) do
{:ok, %{status_code: 200, body: body}} -> {:ok, body}
{:error, %{reason: :timeout}} ->
case retry(tries, options) do
{:ok, :retry} -> request(uri, options, tries + 1)
{:error, :out_of_tries} -> {:error, :timeout}
end
_ -> {:error, :arc_httpoison_error}
end
end
defp retry(tries, options) do
cond do
tries < options[:max_retries] ->
backoff = round(options[:backoff_factor] * :math.pow(2, tries - 1))
backoff = :erlang.min(backoff, options[:backoff_max])
:timer.sleep(backoff)
{:ok, :retry}
true -> {:error, :out_of_tries}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment