Current section

Files

Jump to
rclex lib rclex publisher.ex
Raw

lib/rclex/publisher.ex

defmodule Rclex.Publisher do
@moduledoc false
use GenServer, restart: :temporary
require Logger
alias Rclex.Nif
def start_link(args) do
message_type = Keyword.fetch!(args, :message_type)
topic_name = Keyword.fetch!(args, :topic_name)
name = Keyword.fetch!(args, :name)
namespace = Keyword.fetch!(args, :namespace)
GenServer.start_link(__MODULE__, args, name: name(message_type, topic_name, name, namespace))
end
def name(message_type, topic_name, name, namespace \\ "/") do
{:global, {:publisher, message_type, topic_name, name, namespace}}
end
def publish(%message_type{} = message, topic_name, name, namespace \\ "/") do
case GenServer.whereis(name(message_type, topic_name, name, namespace)) do
nil -> {:error, :not_found}
{_atom, _node} -> raise("should not happen")
pid -> GenServer.call(pid, {:publish, message})
end
end
# callbacks
def init(args) do
Process.flag(:trap_exit, true)
node = Keyword.fetch!(args, :node)
message_type = Keyword.fetch!(args, :message_type)
topic_name = Keyword.fetch!(args, :topic_name)
name = Keyword.fetch!(args, :name)
namespace = Keyword.fetch!(args, :namespace)
qos = Keyword.get(args, :qos, Rclex.QoS.profile_default())
type_support = apply(message_type, :type_support!, [])
publisher = Nif.rcl_publisher_init!(node, type_support, ~c"#{topic_name}", qos)
{:ok,
%{
node: node,
publisher: publisher,
message_type: message_type,
topic_name: topic_name,
name: name,
namespace: namespace
}}
end
def terminate(reason, state) do
Nif.rcl_publisher_fini!(state.publisher, state.node)
Logger.debug("#{__MODULE__}: #{inspect(reason)} #{Path.join(state.namespace, state.name)}")
end
def handle_call({:publish, data}, _from, %{message_type: message_type} = state) do
message = apply(message_type, :create!, [])
try do
:ok = apply(message_type, :set!, [message, data])
:ok = Nif.rcl_publish!(state.publisher, message)
after
:ok = apply(message_type, :destroy!, [message])
end
{:reply, :ok, state}
end
end