Packages
fermo
0.16.1
0.20.1
0.20.0
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.17.1
0.17.0
0.16.7
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.0
0.14.9
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.9
0.13.8
0.13.7
0.13.6
0.13.5
0.13.4
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.1
0.11.0
0.10.0
0.9.1
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.4
0.2.2
0.2.1
0.2.0
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
A static site generator
Current section
Files
Jump to
Current section
Files
lib/fermo/live/socket_registry.ex
defmodule Fermo.Live.SocketRegistry do
use GenServer
@name :fermo_registry
def init(_opts) do
{:ok, %{}}
end
def start_link(_opts) do
GenServer.start_link(__MODULE__, nil, name: @name)
end
def subscribe(path, pid) when is_pid(pid) do
path = if String.ends_with?(path, "/"), do: path, else: path <> "/"
GenServer.call(@name, {:subscribe, path, pid})
end
def unsubscribe(pid) do
GenServer.call(@name, {:unsubscribe, pid})
end
def subscribed() do
GenServer.call(@name, {:subscribed})
end
def subscribed(paths) when is_list(paths) do
Enum.map(paths, &(subscribed(&1)))
|> List.flatten()
end
def subscribed(path) when is_binary(path) do
GenServer.call(@name, {:subscribed, path})
end
def subscribed(%Regex{} = path) do
GenServer.call(@name, {:subscribed, path})
end
def reload_all() do
subscribed()
|> Enum.each(fn pid ->
send(pid, {:reload})
end)
{:ok}
end
def reload(path) do
subscribed(path)
|> Enum.each(fn pid ->
send(pid, {:reload})
end)
{:ok}
end
def handle_call({:subscribe, path, pid}, _from, registry) do
subscribed = [pid | registry[path] || []]
Process.monitor(pid)
registry = Map.put(registry, path, subscribed)
{:reply, :ok, registry}
end
def handle_call({:unsubscribe, pid}, _from, registry) do
{:reply, :unsubscribed, unsubscribe_pid(registry, pid)}
end
def handle_call({:subscribed, %Regex{} = match}, _from, registry) do
matching =
registry
|> Enum.filter(fn {path, _pids} -> String.match?(path, match) end)
|> List.flatten()
{:reply, matching, registry}
end
def handle_call({:subscribed, path}, _from, registry) when is_binary(path) do
{:reply, Map.get(registry, path, []), registry}
end
def handle_call({:subscribed}, _from, registry) do
all_pids = Enum.map(registry, fn {_path, pids} -> pids end)
|> List.flatten()
{:reply, all_pids, registry}
end
def handle_info({:DOWN, _ref, :process, pid, _reason}, registry) do
{:noreply, unsubscribe_pid(registry, pid)}
end
def handle_info(_info, registry), do: {:noreply, registry}
defp unsubscribe_pid(registry, pid) do
Enum.reduce(registry, %{}, fn {path, pids}, acc ->
other = Enum.filter(pids, &(&1 != pid))
Map.put(acc, path, other)
end)
end
end