Current section
Files
Jump to
Current section
Files
lib/push_ex_web/channels/socket_drainer.ex
defmodule PushExWeb.SocketDrainer do
@moduledoc false
use GenServer
require Logger
def child_spec(options) when is_list(options) do
tracker_ref = Keyword.get(options, :tracker_ref, PushEx.Instrumentation.Tracker)
shutdown = Keyword.fetch!(options, :shutdown)
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [tracker_ref]},
shutdown: shutdown
}
end
def start_link(tracker_ref) do
GenServer.start_link(__MODULE__, [tracker_ref])
end
def init([tracker_ref]) do
Process.flag(:trap_exit, true)
{:ok, tracker_ref}
end
def terminate(_reason, tracker_ref) do
Logger.info("Waiting for sockets to drain for PushExWeb.PushSocket #{inspect(tracker_ref)}...")
:ok = wait_for_drain_loop(tracker_ref)
Logger.info("Sockets successfully drained for PushExWeb.PushSocket #{inspect(tracker_ref)}")
end
defp wait_for_drain_loop(tracker_ref) do
if connected_socket_count(tracker_ref) == 0 do
:ok
else
kill_all_socket_connections(tracker_ref)
Process.sleep(100)
wait_for_drain_loop(tracker_ref)
end
end
defp connected_socket_count(tracker_ref) do
try do
PushEx.Instrumentation.Tracker.connected_socket_count(pid: tracker_ref)
catch
_, _ ->
0
end
end
defp connected_socket_pids(tracker_ref) do
try do
PushEx.Instrumentation.Tracker.connected_transport_pids(pid: tracker_ref)
catch
_, _ ->
[]
end
end
defp kill_all_socket_connections(tracker_ref) do
connected_socket_pids(tracker_ref)
|> Enum.each(fn pid ->
send(pid, %Phoenix.Socket.Broadcast{event: "disconnect"})
end)
end
end