-
-
Save ericgoodwin/0d7dcd9d0f43c75337dc43a5df0423b2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Search do | |
use GenServer | |
@pool_name :search_pool | |
@client_options [pool: false, timeout: 30_000, recv_timeout: 5_000, with_body: true] | |
defmodule Config do | |
defstruct uri: nil, index: nil, client: nil, headers: [], transport: :hackney_ssl_transport | |
@type t :: %Config{ | |
uri: URI.t, | |
index: binary, | |
client: any, # Hackney client | |
headers: list, # Default HTTP headers to include on requests | |
transport: atom # Transport to use in the Hackney client | |
} | |
end | |
@doc "Supervisor child spec for a pool of search workers" | |
def child_spec do | |
pool_options = [ | |
name: {:local, @pool_name}, | |
worker_module: __MODULE__, | |
size: 5, | |
max_overflow: 0 | |
] | |
:poolboy.child_spec(@pool_name, pool_options, []) | |
end | |
# ---------------------------------------------------------------------------- | |
# GenServer Setup | |
# ---------------------------------------------------------------------------- | |
def start_link([]) do | |
GenServer.start_link(__MODULE__, []) | |
end | |
def init(_) do | |
Process.flag(:trap_exit, true) | |
{:ok, get_config()} | |
end | |
def terminate(_, %Config{client: nil}), do: | |
:ok | |
def terminate(_, %Config{client: client}) do | |
:hackney.close(client) | |
:ok | |
end | |
# ---------------------------------------------------------------------------- | |
# Public Interface | |
# ---------------------------------------------------------------------------- | |
def index(path, body) do | |
:poolboy.transaction(@pool_name, &GenServer.call(&1, {:index, path, body}, @timeout_ms), @transaction_timeout_ms) | |
end | |
# ---------------------------------------------------------------------------- | |
# GenServer Callbacks | |
# ---------------------------------------------------------------------------- | |
def handle_call({:index, path, body}, _, state = %Config{index: index}) do | |
{:ok, _, _, new_state} = do_request(:put, path, body, state) | |
{:reply, :ok, new_state} | |
end | |
# ---------------------------------------------------------------------------- | |
# Private Functions | |
# ---------------------------------------------------------------------------- | |
@spec do_request(method, binary, map | binary, Config.t) :: response | |
defp do_request(method, path, body, state) when is_map(body), do: | |
do_request(method, path, Poison.encode!(body), state) | |
defp do_request(method, path, body, state) do | |
%{headers: headers, client: client} = new_state = maybe_connect(state) | |
case :hackney.send_request(client, {method, path, headers, body}) do | |
{:ok, status, _headers, body} -> | |
{:ok, status, Poison.Parser.parse!(body), new_state} | |
{:error, :closed} -> | |
:hackney.close(client) | |
do_request(method, path, body, %{new_state | client: nil}) | |
{:error, reason} -> | |
{:error, reason, new_state} | |
end | |
end | |
defp maybe_connect(%Config{uri: uri, client: nil, transport: transport} = state) do | |
{:ok, client} = :hackney.connect(transport, uri.host, uri.port, @client_options) | |
%{state | client: client} | |
end | |
defp maybe_connect(%Config{} = state) do | |
state | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment