haskell - 处理 yesod-websockets 中的断开连接
问题描述
我正在尝试让 yesod-websockets 与我的引导式基于 postgresql 的 yesod 应用程序一起工作。websocket 应该作为 postgres 表的实时更新,因此我需要维护一个包含已连接客户端列表及其 userId 的状态。websocket断开连接后如何运行函数?从更大的角度来看,这个函数应该用于从状态列表中删除 websocket 连接。
到目前为止我所拥有的:
type LobbyState = [(UserId, WS.Connection)]
addClient :: (UserId, WS.Connection) -> LobbyState -> LobbyState
addClient (userId, conn) state = (userId, conn) : state
chatApp :: UserId -> WebSocketsT Handler ()
chatApp userId = do
conn <- ask
-- connections is a MVar [(UserId, WS.Connection)]
connections <- lobbyConnections <$> getYesod
modifyMVar_ connections $ \s -> do
let s' = addClient (userId, conn) s
return s'
-- how to wait for disconnect and execute a function?
getGameR :: Handler TypedContent
getGameR = do
-- TODO: correct usage??
userId <- requireAuthId
webSockets $ chatApp userId
-- some more normal HTML handler code
在示例中,他们使用以下代码段:
race_
(forever $ atomically (readTChan readChan) >>= sendTextData)
(sourceWS $$ mapM_C (\msg ->
atomically $ writeTChan writeChan $ name <> ": " <> msg))
我了解如何利用 aTChan
来永久发送更新,但是如何对实际的断开连接事件做出反应以清理某些状态?
解决方案
感谢 Chris Stryczynski 的评论,我能够通过 catch 处理程序解决它。
在客户端断开连接后进行清理的示例回显服务器可能如下所示:
chatApp :: WebSocketsT Handler ()
chatApp =
( forever $ do
msg :: Text <- receiveData
sendTextData msg
)
`catch` ( \(e :: ConnectionException) -> do
let eshow = fromString $ show e
putStrLn $ eshow
-- clean up specific state here
case e of
CloseRequest code msg -> -- Handle specific close codes/msg
return ()
)
推荐阅读
- node.js - 没有得到猫鼬模型的响应。find()查询
- python - Pandas 中的同比增长列计算
- karate - 即使定位器在 DOM 中可用,Assert exists().exists 也会返回评估为 false 的断言
- android - 使用地图框:错误(评估'MapboxGL.StyleURL')
- python - 使用 print(", ".join(my_array)) 提取单个字符串并将其添加到 streamlit markdown。我没有得到字符串,而是得到了 NONE
- docker - 在 docker build 中打印 ARG 值
- git - 第一次运行时出现“包 org.junit 不存在”
- sqlite - 即使存在,Sqlite INSERT 也会返回行 ID
- java - 知道为什么 JFrame 会出现这个故障吗?
- node.js - 所有页面都必须使用react吗?