Current section
Files
Jump to
Current section
Files
lib/yggdrasil/adapter/elixir.ex
defmodule Yggdrasil.Adapter.Elixir do
@moduledoc """
Default Elixir adapter. Events are generated by notifying the adapter server.
"""
use YProcess, backend: Yggdrasil.Backend
use Yggdrasil.Adapter, module: YProcess
alias Yggdrasil.Adapter
alias Yggdrasil.Publisher
##
# State for the Elixir adapter.
defstruct [:channel, :publisher, :connected?, :pid]
alias __MODULE__, as: State
##
# Generates the `channel` name.
@doc false
def get_channel_name(channel) do
{:elixir_adapter, channel}
end
@doc false
def is_connected?(adapter) do
task = Task.async(fn ->
case YProcess.call(adapter, {:connected?, self()}) do
true -> true
false ->
receive do
:connected? -> true
_ -> false
after
5000 -> false
end
end
end)
Task.await(task)
end
@doc false
def init(%Adapter{publisher: publisher, channel: channel}) do
adapter_channel = get_channel_name(channel)
state = %State{channel: adapter_channel, publisher: publisher,
connected?: false, pid: nil}
{:join, [adapter_channel], state}
end
@doc false
def ready(:joined, _channels, %State{pid: pid} = state) when is_pid(pid) do
send pid, :connected?
new_state = %State{state | connected?: true, pid: nil}
{:noreply, new_state}
end
def ready(:joined, _channels, %State{} = state) do
new_state = %State{state | connected?: true, pid: nil}
{:noreply, new_state}
end
@doc false
def handle_call({:connected?, _}, _, %State{connected?: true} = state) do
{:reply, true, state}
end
def handle_call({:connected?, pid}, _, %State{connected?: false} = state) do
new_state = %State{state | pid: pid}
{:reply, false, new_state}
end
@doc false
def handle_event(
channel,
message,
%State{channel: channel, publisher: publisher} = state
) do
Publisher.sync_notify(publisher, channel, message)
{:noreply, state}
end
def handle_event(_, _, state) do
{:noreply, state}
end
end