add presence client

This commit is contained in:
Berenice Medel 2021-12-08 23:33:29 -06:00 committed by Chris McCord
parent 216916817b
commit bd927bf8b2
4 changed files with 117 additions and 5 deletions

View file

@ -20,9 +20,10 @@ defmodule LiveBeats.Application do
#start presence #start presence
LiveBeatsWeb.Presence, LiveBeatsWeb.Presence,
# Start the Endpoint (http/https) # Start the Endpoint (http/https)
LiveBeatsWeb.Endpoint LiveBeatsWeb.Endpoint,
# Start a worker by calling: LiveBeats.Worker.start_link(arg) # Start a worker by calling: LiveBeats.Worker.start_link(arg)
# {LiveBeats.Worker, arg} # {LiveBeats.Worker, arg}
{Phoenix.Presence.Client, client: LiveBeats.PresenceClient, pubsub: LiveBeats.PubSub, presence: LiveBeats.Presence}
] ]
# See https://hexdocs.pm/elixir/Supervisor.html # See https://hexdocs.pm/elixir/Supervisor.html

View file

@ -0,0 +1,85 @@
defmodule Phoenix.Presence.Client do
use GenServer
@doc """
TODO
## Options
* `:pubsub` - The required name of the pubsub server
* `:presence` - The required name of the presence module
* `:client` - The required callback module
"""
def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: PresenceClient)
end
def track(topic, key, meta) do
GenServer.call(PresenceClient, {:track, self(), topic, key, meta})
end
def untrack(topic, key) do
GenServer.call(PresenceClient, {:untrack, self(), topic, key})
end
def init(opts) do
client = Keyword.fetch!(opts, :client)
client_state = client.init(%{})
state = %{
topics: %{},
client: client,
pubsub: Keyword.fetch!(opts, :pubsub),
presence_mod: Keyword.fetch!(opts, :presence),
client_state: client_state
}
{:ok, state}
end
def handle_info(%{topic: topic, event: "presence_diff", payload: diff}, state) do
{:noreply, merge_diff(state, topic, diff)}
end
def handle_call({:track, pid, topic, key, meta}, _from, state) do
{:reply, :ok, track_pid(state, pid, topic, key, meta)}
end
def handle_call({:untrack, pid, topic, key}, _from, state) do
{:reply, :ok, untrack_pid(state, pid, topic, key)}
end
defp track_pid(state, pid, topic, key, meta) do
case Map.fetch(state.topics, topic) do
{:ok, presences} ->
state.presence_mod.track(pid, topic, key, meta)
# update topics state...
# new_state
state
:error ->
# subscribe to topic we weren't yet tracking
Phoenix.PubSub.subscribe(state.pubsub, topic)
# new_state
state
end
end
defp untrack_pid(state, pid, topic, key) do
state.presence_mod.untrack(pid, topic, key)
# remove presence from state.topics
# if no more presences for given topic, unsubscribe
# Phoenix.PubSub.unsubscribe(state.pubsub, topic)
# new_state
state
end
defp merge_diff(state, topic, diff) do
# merge diff into state.topics
# invoke state.client.handle_join|handle_leave
# if no more presences for given topic, unsubscribe
# Phoenix.PubSub.unsubscribe(state.pubsub, topic)
# new_state
state
end
end

View file

@ -0,0 +1,28 @@
defmodule LiveBeats.PresenceClient do
@behaviour Phoenix.Presence.Client
@presence LiveBeats.Presence
def start_link(opts) do
Phoenix.Presence.Client.start_link(presence: @presence, client: __MODULE__)
end
def list(topic) do
@presence.list(topic)
end
def init(_opts) do
# user-land state
{:ok, %{}}
end
def handle_join(key, presence, state) do
# can local pubsub to LVs about new join
{:ok, state}
end
def handle_leave(key, presence, state) do
# can local pubsub to LVs about new leave
{:ok, state}
end
end

View file

@ -87,11 +87,9 @@ defmodule LiveBeatsWeb.ProfileLive do
if connected?(socket) do if connected?(socket) do
MediaLibrary.subscribe_to_profile(profile) MediaLibrary.subscribe_to_profile(profile)
Accounts.subscribe(current_user.id) Accounts.subscribe(current_user.id)
LiveBeatsWeb.Presence.track( Phoenix.Presence.Client.track(topic(profile.user_id),
self(),
topic(profile.user_id),
current_user.id, current_user.id,
current_user %{}
) )
end end