Как использовать Network.WebSockets.Snap в оснастке?

Было бы неплохо иметь возможность использовать Network.WebSockets модуль изнутри, но я не могу понять, как на самом деле это сделать.

С использованием runWebSocketsSnap :: MonadSnap m => ServerApp -> m () функция от Network.WebSockets.Snap в мое приложение легко включить простой сервер веб-сокетов без сохранения состояния:

routes :: [(ByteString, Handler App App ())]
routes = [ ("/ws", runWebSocketsSnap wsApp) ]

wsApp :: PendingConnection -> IO () -- this is the ServerApp type
wsApp pending = do
    conn <- acceptRequest pending
    forever $ do
        msg <- receiveData conn
        sendTextData conn ("Echo " `mappend` msg :: Text)

Но моя цель - сохранить состояние для веб-сервера (например, список подключенных клиентов, как в http://jaspervdj.be/websockets/example.html). В качестве альтернативы, доступ к хранилищу щелевых кислотных состояний будет отличным.

Моей первой идеей было liftIO действия websocket в Handler App App Монада, и напишите приложение, как это:

wsApp :: PendingConnection -> Handler App App ()
wsApp pending = do
    conn <- liftIO $ acceptRequest pending
    forever $ do
        msg <- liftIO $ receiveData conn
        update (SetLastMsg msg)
        liftIO $ sendTextData conn ("Stored msg in datastore.")

Но нет версии runWebSocketsSnap это берет приложение вышеупомянутой формы, и я не могу понять, как изменить существующий ( источник на взломе). Мне кажется, нужна альтернатива forkIO который принимает меры в Handler App App вместо монады, но мое понимание Haskell и особенно параллелизма в Snap заканчивается здесь...

1 ответ

Решение

Функция runWebSocketsSnap требует, чтобы ее аргумент был типа PendingConnection -> IO (), Это означает, что вы не можете напрямую получить доступ к структуре данных вашего приложения внутри этой функции. Что вам нужно сделать, это передать информацию в функцию в качестве аргумента примерно так.

routes = [ ("/ws", webSocketsDriver) ]

webSocketsDriver :: Handler App App ()
webSocketsDriver = do
    appState <- get
    runWebSocketsSnap (wsApp appState)

wsApp :: App -> PendingConnection -> IO ()
wsApp app pending = do
    ...
Другие вопросы по тегам