在 yesod-websockets 中处理断开连接

Handling disconnects in yesod-websockets

我正在尝试让 yesod-websockets 与我的基于 postgresql 的引导式 yesod 应用程序一起工作。 websocket 应该充当 postgres table 的实时更新,因此我需要维护一个包含已连接客户端列表及其用户 ID 的状态。一旦 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))

我了解如何利用 TChan 永远发送更新,但我如何对实际断开连接事件作出反应以清理某些状态?

感谢 Chris Stryczynski 的评论,我能够通过捕获处理程序解决它。

在客户端断开连接后进行清理的示例回显服务器可能如下所示:

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 ()
            )