Packages
mojito_fresha
0.7.13
Mojito client but with castore updated, forked from https://github.com/surgeventures/mojito
Current section
Files
Jump to
Current section
Files
lib/mojito/pool/poolboy.ex
defmodule Mojito.Pool.Poolboy do
@moduledoc false
## Mojito.Pool.Poolboy is an HTTP client with high-performance, easy-to-use
## connection pools based on the Poolboy library.
##
## Pools are maintained automatically by Mojito, requests are matched to
## the correct pool without user intervention, and multiple pools can be
## used for the same destination in order to reduce concurrency bottlenecks.
##
## Config parameters are explained in the `Mojito` moduledocs.
@behaviour Mojito.Pool
alias Mojito.{Config, Request, Utils}
require Logger
@doc ~S"""
Performs an HTTP request using a connection pool, creating that pool if
it didn't already exist. Requests are always matched to a pool that is
connected to the correct destination host and port.
"""
@impl true
def request(%{} = request) do
with {:ok, valid_request} <- Request.validate_request(request),
{:ok, _proto, host, port} <- Utils.decompose_url(valid_request.url),
pool_key <- pool_key(host, port),
{:ok, pool} <- get_pool(pool_key) do
do_request(pool, pool_key, valid_request)
end
end
defp do_request(pool, pool_key, request) do
case Mojito.Pool.Poolboy.Single.request(pool, request) do
{:error, %{reason: :checkout_timeout}} ->
case start_pool(pool_key) do
{:ok, pid} ->
Mojito.Pool.Poolboy.Single.request(pid, request)
error ->
error
end
other ->
other
end
end
## Returns a pool for the given destination, starting one or more
## if necessary.
@doc false
@spec get_pool(any) :: {:ok, pid} | {:error, Mojito.error()}
def get_pool(pool_key) do
case get_pools(pool_key) do
[] ->
opts = Mojito.Pool.pool_opts(pool_key)
1..opts[:pools] |> Enum.each(fn _ -> start_pool(pool_key) end)
get_pool(pool_key)
pools ->
{:ok, Enum.random(pools)}
end
end
## Returns all pools for the given destination.
@doc false
@spec get_pools(any) :: [pid]
defp get_pools(pool_key) do
Mojito.Pool.Poolboy.Registry
|> Registry.lookup(pool_key)
|> Enum.map(fn {_, pid} -> pid end)
end
## Starts a new pool for the given destination.
@doc false
@spec start_pool(any) :: {:ok, pid} | {:error, Mojito.error()}
def start_pool(pool_key) do
old_trap_exit = Process.flag(:trap_exit, true)
try do
GenServer.call(
Mojito.Pool.Poolboy.Manager,
{:start_pool, pool_key},
Config.timeout()
)
rescue
e -> {:error, e}
catch
:exit, _ -> {:error, :checkout_timeout}
after
Process.flag(:trap_exit, old_trap_exit)
end
|> Utils.wrap_return_value()
end
## Returns a key representing the given destination.
@doc false
@spec pool_key(String.t(), pos_integer) :: Mojito.Pool.pool_key()
def pool_key(host, port) do
{host, port}
end
end