Current section
Files
Jump to
Current section
Files
lib/rpc_load_balancer.ex
defmodule RpcLoadBalancer do
@moduledoc """
Executes Remote Procedure Calls.
This library provides:
- RPC wrappers around `:erpc.call/5` and `:erpc.cast/4`
- A distributed node load balancer built on `:pg`
"""
@spec call(node(), module(), atom(), [any()], timeout: timeout()) :: ErrorMessage.t_res(any())
def call(node, module, fun, args, opts \\ [timeout: :timer.seconds(10)]) do
timeout = Keyword.get(opts, :timeout, :timer.seconds(10))
try do
{:ok, :erpc.call(node, module, fun, args, timeout)}
rescue
e in ErlangError ->
{:error, erlang_error_to_error_message(e, node)}
e ->
{:error, ErrorMessage.service_unavailable("unavailable", %{node: node, details: e})}
end
end
@spec cast(node(), module(), atom(), [term()]) :: :ok | {:error, ErrorMessage.t()}
def cast(node, module, fun, args) do
:erpc.cast(node, module, fun, args)
rescue
e in ErlangError ->
{:error, erlang_error_to_error_message(e, node)}
e ->
{:error, ErrorMessage.service_unavailable("unavailable", %{node: node, details: e})}
end
defp erlang_error_to_error_message(%ErlangError{original: {:erpc, :timeout}}, node) do
ErrorMessage.request_timeout("timeout", %{node: node})
end
defp erlang_error_to_error_message(%ErlangError{original: {:erpc, :noconnection}}, node) do
ErrorMessage.service_unavailable("noconnection", %{node: node})
end
defp erlang_error_to_error_message(%ErlangError{original: {:erpc, :badarg}}, node) do
ErrorMessage.bad_request("bad request", %{node: node})
end
defp erlang_error_to_error_message(%ErlangError{} = error, _node) do
ErrorMessage.service_unavailable("unavailable", %{details: error})
end
end