elixir-tesla / tesla

The flexible HTTP client library for Elixir, with support for middleware and multiple adapters.
MIT License
2k stars 341 forks source link

Retry does not work on timeout #536

Closed MMore closed 2 years ago

MMore commented 2 years ago

Hello,

love your library! I just wanted to add a retry for my existing API client using the Retry middleware. I expected it would retry on timeouts, but it does not. It returns {:error, :timeout} on a timeout, but retry isn't triggered. For other errors retry works as expected.

That's basically my module:

defmodule MyModule.MyApiClient do
    use Tesla

    require Logger

    plug(
      Tesla.Middleware.BaseUrl,
      "https://myurl.com"
    )

    plug(Tesla.Middleware.Headers, [
      {"Content-Type", "application/json; charset=UTF-8"}
    ])

    plug(Tesla.Middleware.Logger, debug: false)

    plug(Tesla.Middleware.Timeout, timeout: 12_000)

    plug(Tesla.Middleware.Retry,
      delay: 500,
      max_retries: 3,
      max_delay: 5_000,
      should_retry: fn
        {:ok, %{status: status}} when status in [400, 500] ->
          IO.puts(:retrying)
          true

        {:ok, _} ->
          false

        {:error, :timeout} ->
          IO.puts(:retrying_timeout)
          true

        {:error, reason} ->
          IO.puts(inspect(reason, pretty: true, limit: :infinity))
          IO.puts(:retrying_error)
          true
      end
    )

    plug(Tesla.Middleware.JSON)

    def new(token) do
      Tesla.client([{Tesla.Middleware.BearerAuth, token: token}])
    end

    def get_items(client) do
      get(client, "/more_url")
    end
  end

The following versions I use:

Any ideas, what I could do? Thank you!

hassanRsiddiqi commented 2 years ago

I am also facing the same issue. @MMore Do you manage it somehow?

teamon commented 2 years ago

You need to put Retry middleware before Timeout middleware.

hassanRsiddiqi commented 2 years ago

@teamon thanks, It works.

yordis commented 2 years ago

@MMore feel free to reopen the issue if the solution that @teamon shared doesn't work