mirror of
https://codeberg.org/JasterV/intisync.ex.git
synced 2026-04-26 18:10:07 +00:00
develop SessionsSupervisor, SessionServer & SessionPubSub
This commit is contained in:
parent
e60e1be337
commit
a03a2b69db
4 changed files with 173 additions and 0 deletions
|
|
@ -11,6 +11,7 @@ defmodule Intisync.Application do
|
|||
IntisyncWeb.Telemetry,
|
||||
{DNSCluster, query: Application.get_env(:intisync, :dns_cluster_query) || :ignore},
|
||||
{Phoenix.PubSub, name: Intisync.PubSub},
|
||||
{Intisync.SessionsSupervisor, %{}},
|
||||
{IntisyncWeb.LiveViewMonitor, %{}},
|
||||
IntisyncWeb.Endpoint
|
||||
]
|
||||
|
|
|
|||
12
lib/intisync/session_pubsub.ex
Normal file
12
lib/intisync/session_pubsub.ex
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
defmodule Intisync.SessionPubSub do
|
||||
def broadcast!(session_id, topic, event, payload) do
|
||||
topic = "#{topic}:#{event}:#{session_id}"
|
||||
payload = %{payload: payload, topic: topic}
|
||||
|
||||
Phoenix.PubSub.broadcast!(Intisync.PubSub, topic, payload)
|
||||
end
|
||||
|
||||
def subscribe!(session_id, topic, event) do
|
||||
:ok = Phoenix.PubSub.subscribe(Intisync.PubSub, "#{topic}:#{event}:#{session_id}")
|
||||
end
|
||||
end
|
||||
121
lib/intisync/session_server.ex
Normal file
121
lib/intisync/session_server.ex
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
defmodule Intisync.SessionServer do
|
||||
alias Intisync.SessionPubSub
|
||||
use GenServer
|
||||
|
||||
def init(session_id) do
|
||||
{:ok,
|
||||
%{
|
||||
session_id: session_id,
|
||||
remote_connection_status: :disconnected,
|
||||
devices: %{}
|
||||
}}
|
||||
end
|
||||
|
||||
def start_link({session_id}) do
|
||||
GenServer.start_link(__MODULE__, session_id, name: {:global, "session:#{session_id}"})
|
||||
end
|
||||
|
||||
def get_id(pid) do
|
||||
GenServer.call(pid, {:get_id})
|
||||
end
|
||||
|
||||
def remote_connected(pid) do
|
||||
GenServer.cast(pid, {:remote_connected})
|
||||
end
|
||||
|
||||
def remote_disconnected(pid) do
|
||||
GenServer.cast(pid, {:remote_disconnected})
|
||||
end
|
||||
|
||||
def device_connected(pid, index, device) do
|
||||
GenServer.call(pid, {:device_connected, index, device})
|
||||
end
|
||||
|
||||
def device_disconnected(pid, index) do
|
||||
GenServer.call(pid, {:device_disconnected, index})
|
||||
end
|
||||
|
||||
def empty_devices(pid) do
|
||||
GenServer.call(pid, {:empty_devices})
|
||||
end
|
||||
|
||||
def vibrate_device(pid, index, vibration) do
|
||||
GenServer.call(pid, {:vibrate_device, index, vibration})
|
||||
end
|
||||
|
||||
def get_devices(pid) do
|
||||
GenServer.call(pid, {:get_devices})
|
||||
end
|
||||
|
||||
def is_full?(pid) do
|
||||
GenServer.call(pid, {:is_full?})
|
||||
end
|
||||
|
||||
def handle_call({:get_id}, _from, state) do
|
||||
{:reply, state.session_id, state}
|
||||
end
|
||||
|
||||
def handle_call({:get_devices}, _from, state) do
|
||||
{:reply, state.devices, state}
|
||||
end
|
||||
|
||||
def handle_call({:is_full?}, _from, state) do
|
||||
is_full? = state.remote_connection_status == :connected
|
||||
|
||||
{:reply, is_full?, state}
|
||||
end
|
||||
|
||||
def handle_call({:device_connected, index, device}, _from, state) do
|
||||
new_devices = Map.put_new(state.devices, index, device)
|
||||
|
||||
GenServer.cast(
|
||||
self(),
|
||||
{:publish, "devices", "connected", %{index: index}}
|
||||
)
|
||||
|
||||
{:reply, :ok, %{state | devices: new_devices}}
|
||||
end
|
||||
|
||||
def handle_call({:device_disconnected, index}, _from, state) do
|
||||
new_devices = Map.delete(state.devices, index)
|
||||
|
||||
GenServer.cast(
|
||||
self(),
|
||||
{:publish, "devices", "disconnected", %{index: index}}
|
||||
)
|
||||
|
||||
{:reply, :ok, %{state | devices: new_devices}}
|
||||
end
|
||||
|
||||
def handle_call({:vibrate_device, index, vibration}, _from, state) do
|
||||
devices = state.devices
|
||||
new_devices = Map.replace!(devices, index, %{devices[index] | vibration: vibration})
|
||||
|
||||
GenServer.cast(
|
||||
self(),
|
||||
{:publish, "devices", "vibrate", %{index: index, vibration: vibration}}
|
||||
)
|
||||
|
||||
{:reply, :ok, %{state | devices: new_devices}}
|
||||
end
|
||||
|
||||
def handle_call({:empty_devices}, _from, state) do
|
||||
GenServer.cast(self(), {:publish, "devices", "empty", %{}})
|
||||
{:reply, :ok, %{state | devices: %{}}}
|
||||
end
|
||||
|
||||
def handle_cast({:remote_connected}, state) do
|
||||
GenServer.cast(self(), {:publish, "remote", "connected", %{}})
|
||||
{:noreply, %{state | remote_connection_status: :connected}}
|
||||
end
|
||||
|
||||
def handle_cast({:remote_disconnected}, state) do
|
||||
GenServer.cast(self(), {:publish, "remote", "disconnected", %{}})
|
||||
{:noreply, %{state | remote_connection_status: :disconnected}}
|
||||
end
|
||||
|
||||
def handle_cast({:publish, topic, event, payload}, state) do
|
||||
SessionPubSub.broadcast!(state.session_id, topic, event, payload)
|
||||
{:noreply, state}
|
||||
end
|
||||
end
|
||||
39
lib/intisync/sessions_supervisor.ex
Normal file
39
lib/intisync/sessions_supervisor.ex
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
defmodule Intisync.SessionsSupervisor do
|
||||
use DynamicSupervisor
|
||||
|
||||
alias Intisync.SessionServer
|
||||
alias Intisync.SessionPubSub
|
||||
|
||||
def start_link(_arg) do
|
||||
DynamicSupervisor.start_link(__MODULE__, :ok, name: __MODULE__)
|
||||
end
|
||||
|
||||
def init(:ok) do
|
||||
DynamicSupervisor.init(strategy: :one_for_one)
|
||||
end
|
||||
|
||||
def start_session(session_id) do
|
||||
child_spec = {SessionServer, {session_id}}
|
||||
DynamicSupervisor.start_child(__MODULE__, child_spec)
|
||||
end
|
||||
|
||||
def whereis(session_id) do
|
||||
GenServer.whereis({:global, "session:#{session_id}"})
|
||||
end
|
||||
|
||||
def close_session(pid) do
|
||||
session_id = SessionServer.get_id(pid)
|
||||
SessionPubSub.broadcast!(session_id, "session", "closed", %{})
|
||||
DynamicSupervisor.terminate_child(__MODULE__, pid)
|
||||
end
|
||||
|
||||
# Nice utility method to check which processes are under supervision
|
||||
def children do
|
||||
DynamicSupervisor.which_children(__MODULE__)
|
||||
end
|
||||
|
||||
# Nice utility method to check which processes are under supervision
|
||||
def count_children do
|
||||
DynamicSupervisor.count_children(__MODULE__)
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue