Current section

Files

Jump to
soulless lib soulless rpc.ex
Raw

lib/soulless/rpc.ex

defmodule Soulless.RPC do
def send(packet, client) do
GenServer.cast(client, {:send, packet})
end
def fetch(packet, client) do
GenServer.call(client, {:send, packet})
end
defp generate_rpc_modules(packet_type, namespace, proto_namespace) do
services = generate_rpc_funs(packet_type, proto_namespace)
for {service_name, methods} <- services do
module_name = Module.concat([namespace, service_name])
quote do
defmodule unquote(module_name) do
unquote(methods)
end
end
end
end
defp generate_rpc_funs(packet_type, namespace) do
descriptor = SoullessProto.descriptor()
{_, package} = List.keyfind!(descriptor, :package, 0)
for {type, service} <- descriptor, type == :service, into: %{} do
service_name = Keyword.get(service, :name)
methods =
Keyword.get(service, :methods)
|> Enum.map(fn {:method, rpc} ->
build_rpc_fun(packet_type, namespace, package, service_name, rpc)
end)
{service_name, methods}
end
end
defp build_rpc_fun(packet_type, namespace, package, service_name, rpc) do
{:custom, request_type} = Keyword.get(rpc, :request_type)
function = Keyword.get(rpc, :name)
request_module = Module.concat([namespace, String.capitalize(package), request_type])
function_name = function |> Macro.underscore() |> String.to_atom()
is_empty = Enum.empty?(request_module.schema().fields)
message =
if is_empty do
quote do
%unquote(request_module){}
end
else
quote do
payload
end
end
body =
quote do
%unquote(packet_type){
kind: :request,
body: unquote(message),
rpc: unquote(".#{package}.#{service_name}.#{function}")
}
end
if is_empty do
quote do
def unquote(function_name)() do
unquote(body)
end
end
else
quote do
def unquote(function_name)(%unquote(request_module){} = payload) do
unquote(body)
end
end
end
end
defmacro __using__(opts) do
{opts, _} = Code.eval_quoted(opts)
namespace = Keyword.fetch!(opts, :namespace)
proto_namespace = Keyword.fetch!(opts, :proto_namespace)
packet_type = Keyword.fetch!(opts, :packet_type)
generate_rpc_modules(packet_type, namespace, proto_namespace)
end
end