defmodule PhaseDB.Client.Request do alias PhaseDB.Client.RequestSupervisor alias PhaseDB.Request, as: DBRequest alias PhaseDB.Result, as: DBResponse alias PhaseDB.Client.Connection use GenServer @moduledoc """ Handles sending a request to a connection and awaiting a response. """ def create query, connection_pid do Supervisor.start_child RequestSupervisor, [query, connection_pid] end def await pid, timeout \\ 5000 do GenServer.call pid, :await, timeout end def start_link query, connection_pid do GenServer.start_link __MODULE__, [query, connection_pid] end def init [query, connection_pid] do request = DBRequest.create query state = %{ query: query, connection_pid: connection_pid, request: request, response: nil, id: request.id, reply_to: [] } key = {:p, :l, {__MODULE__, connection_pid}} :gproc.reg key Connection.xmit connection_pid, {:text, Poison.encode!(request)} {:ok, state} end def handle_call :await, from, %{reply_to: reply_to}=state do {:noreply, %{state | reply_to: [from | reply_to]}} end def handle_info {:text, json}, state do response = DBResponse.from_json(json) handle_response response, state end defp handle_response(%{id: id1}=response, %{id: id2, reply_to: reply_to}=state) when id1 == id2 do Enum.each reply_to, fn(from)-> GenServer.reply from, response end {:stop, :normal, %{state | response: response, reply_to: []}} end defp handle_response response, state do raise "ignoring result #{inspect response}" {:noreply, state} end end