Current section

Files

Jump to
antl_utils_elixir lib rpc_client.ex
Raw

lib/rpc_client.ex

defmodule AntlUtilsElixir.RpcClient do
@moduledoc "A tiny Rpc Client"
defmodule NodeDownError do
defexception [:message]
end
defmodule BadCallError do
defexception [:message]
end
require Logger
@doc """
Executes functions on a remote node.
Logs call and response.
## Examples
iex> AntlUtilsElixir.RpcClient.call(:node, Kernel, :+, [1, 2])
3
iex> AntlUtilsElixir.RpcClient.call(:node, Kernel, :undefined_function, [1, 2])
{:error, :failed}
"""
@spec call(atom, atom, atom, [any]) :: any
def call(remote_node, module, function_name, attributes)
when is_atom(module) and is_atom(function_name) and is_list(attributes) do
call_and_log(remote_node, module, function_name, attributes)
|> process_response()
end
@doc """
Similar to `call/4` but raises if the call failed.
## Examples
iex> AntlUtilsElixir.RpcClient.call!(:node, Kernel, :+, [1, 2])
3
iex> AntlUtilsElixir.RpcClient.call!(:node, Kernel, :undefined_function, [1, 2])
(** RpcError) got: "failure reason"
"""
@spec call!(atom, atom, atom, [any]) :: any
def call!(remote_node, module, function_name, attributes) do
call_and_log(remote_node, module, function_name, attributes)
|> process_response!()
end
defp call_and_log(remote_node, module, function_name, attributes)
when is_atom(module) and is_atom(function_name) and is_list(attributes) do
Logger.debug("#{remote_node} - #{module} - #{function_name} - #{inspect(attributes)}")
:rpc.call(remote_node, module, function_name, attributes)
|> log_response()
end
defp log_response(response) do
Logger.debug(inspect(response))
response
end
defp process_response({:badrpc, :nodedown}), do: {:error, :nodedown}
defp process_response({:badrpc, _error}), do: {:error, :failed}
defp process_response(response), do: response
defp process_response!({:badrpc, :nodedown}),
do: raise(AntlUtilsElixir.RpcClient.NodeDownError, "unable to connect to node")
defp process_response!({:badrpc, error}),
do: raise(AntlUtilsElixir.RpcClient.BadCallError, inspect(error))
defp process_response!(response), do: response
end