Current section

Files

Jump to
tesla lib tesla middleware timeout.ex
Raw

lib/tesla/middleware/timeout.ex

defmodule Tesla.Middleware.Timeout do
@behaviour Tesla.Middleware
@moduledoc """
Timeout http request after X seconds.
### Example
```
defmodule MyClient do
use Tesla
plug Tesla.Middleware.Timeout, timeout: 2_000
end
```
### Options
- `:timeout` - number of milliseconds a request is allowed to take (defaults to 1000)
"""
@default_timeout 1_000
def call(env, next, opts) do
opts = opts || []
timeout = Keyword.get(opts, :timeout, @default_timeout)
task = safe_async(fn -> Tesla.run(env, next) end)
try do
task
|> Task.await(timeout)
|> repass_error
catch
:exit, {:timeout, _} ->
Task.shutdown(task, 0)
{:error, :timeout}
end
end
defp safe_async(func) do
Task.async(fn ->
try do
{:ok, func.()}
rescue
e in _ ->
{:exception, e}
catch
type, value ->
{type, value}
end
end)
end
defp repass_error({:exception, error}), do: raise(error)
defp repass_error({:throw, value}), do: throw(value)
defp repass_error({:exit, value}), do: exit(value)
defp repass_error({:ok, result}), do: result
end