捕获 websocket 的网络连接中断

前端之家收集整理的这篇文章主要介绍了捕获 websocket 的网络连接中断前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

当网络连接突然断开时,channel 中的 terminate 函数是不会执行的. 为了捕获到客户端的网络连接中断,我们需要不捕获 channel 的退出(因为它不会退出),而是需要由另一个进程来监控.

# lib/my_app.ex

children = [
...
worker(ChannelWatcher,[:rooms])
]

web/channels/room_channel.ex

def join("rooms:" <> id,params,socket) do
uid = socket.assigns.user_id
:ok = ChannelWatcher.monitor(:rooms,self(),{MODULE,:leave,[id,uid]})

{:ok,socket}
end

def leave(room_id,user_id) do

handle user leaving

end

lib/my_app/channel_watcher.ex

defmodule ChannelWatcher do
use GenServer

Client API

def monitor(server_name,pid,mfa) do
GenServer.call(server_name,{:monitor,mfa})
end

def demonitor(server_name,pid) do
GenServer.call(server_name,{:demonitor,pid})
end

Server API

def start_link(name) do
GenServer.start_link(MODULE,[],name: name)
end

def init(_) do
Process.flag(:trap_exit,true)
{:ok,%{channels: HashDict.new()}}
end

def handle_call({:monitor,mfa},_from,state) do
Process.link(pid)
{:reply,:ok,put_channel(state,mfa)
end

def handle_call(:demonitor,pid},state) do
case HashDict.fetch(state.channels,pid) do
:error -> {:reply,state}
{:ok,_mfa} ->
Process.unlink(pid)
{:reply,drop_channel(state,pid)}
end
end

def handle_info({:EXIT,_reason},pid) do
:error -> {:noreply,{mod,func,args}} ->
Task.start_link(fn -> apply(mod,args) end)
{:noreply,pid)}
end
end

defp drop_channel(state,pid) do
%{state | channels: HashDict.delete(state.channels,pid)}}
end

defp put_channel(state,mfa) do
%{state | channels: HashDict.put(channels,mfa)}}
end
end

猜你在找的程序笔记相关文章