Current section

Files

Jump to
yggdrasil lib yggdrasil adapter bridge subscriber.ex
Raw

lib/yggdrasil/adapter/bridge/subscriber.ex

defmodule Yggdrasil.Adapter.Bridge.Subscriber do
@moduledoc """
This module defines a bridge remote subscriber.
"""
use GenServer
require Logger
alias Yggdrasil.Channel
@doc false
defstruct [:target, :pid, :channel]
alias __MODULE__, as: State
@doc """
Starts a bridge remote subscriber.
"""
@spec start_link(pid(), Channel.t(), Channel.t()) :: GenServer.on_start()
@spec start_link(pid(), Channel.t(), Channel.t(), GenServer.options()) ::
GenServer.on_start()
def start_link(pid, target, channel, options \\ []) do
state = %State{target: target, channel: channel, pid: pid}
GenServer.start_link(__MODULE__, state, options)
end
@doc """
Stops a bridge remote subscriber.
"""
@spec stop(GenServer.server()) :: :ok
@spec stop(GenServer.server(), term()) :: :ok
@spec stop(GenServer.server(), term(), non_neg_integer() | :infinity) :: :ok
defdelegate stop(bridge, reason \\ :normal, timeout \\ :infinity),
to: GenServer
@impl GenServer
def init(%State{pid: pid, channel: channel} = state) do
Process.flag(:trap_exit, true)
Process.monitor(pid)
case Yggdrasil.subscribe(channel) do
:ok ->
Logger.debug(fn ->
"Started #{__MODULE__} for #{inspect(pid)} and #{inspect(channel)}"
end)
{:ok, state}
{:error, reason} ->
Logger.error(fn ->
"Cannot start #{__MODULE__} due to #{inspect(reason)}"
end)
{:stop, reason}
end
end
@impl GenServer
def handle_info({:Y_CONNECTED, _}, %State{target: target} = state) do
Yggdrasil.publish(target, :Y_CONNECTED)
{:noreply, state}
end
def handle_info({:Y_EVENT, _, message}, %State{target: target} = state) do
Yggdrasil.publish(target, message)
{:noreply, state}
end
def handle_info({:Y_DISCONNECTED, _}, %State{target: target} = state) do
Yggdrasil.publish(target, :Y_DISCONNECTED)
{:noreply, state}
end
def handle_info({:DOWN, _, _, _, _}, %State{} = state) do
{:stop, :normal, state}
end
def handle_info(_, %State{} = state) do
{:noreply, state}
end
@impl GenServer
def terminate(:normal, %State{pid: pid, channel: channel}) do
Yggdrasil.unsubscribe(channel)
Logger.debug(fn ->
"Stopped #{__MODULE__} for #{inspect(pid)} and #{inspect(channel)}"
end)
end
def terminate(reason, %State{pid: pid, channel: channel}) do
Yggdrasil.unsubscribe(channel)
Logger.warn(fn ->
"Stopped #{__MODULE__} for #{inspect(pid)} and #{inspect(channel)}" <>
" due to #{inspect(reason)}"
end)
end
end