I've been using reflex and reflex-dom to recreate a web version of a boardgame, and I quite like it so far, but I require a websocket to alert a player when the other player has made a move.
Everything works great but if the server goes down, I can't find a way to detect that it happened and reconnect. Additionally, if you send an event to a server while it is down, it is just is eaten up without any error.
I'm using a stripped down version of the websockets example from https://github.com/reflex-frp/reflex-examples/blob/master/websocket-echo/src/Main.hs
{-# LANGUAGE RecursiveDo #-}
module Lib where
import Data.Monoid
import Reflex.Dom
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8, decodeUtf8)
wsurl = "ws://127.0.0.1:5714"
-- wsurl = "ws://echo.websocket.org"
someFunc = mainWidget $ do
rec t <- textInput $ def & setValue .~ fmap (const "") newMessage
b <- button "Send"
text $ "Sending to " <> wsurl
let newMessage = fmap ((:[]) . encodeUtf8 . T.pack) $ tag (current $ value t) $ leftmost [b, textInputGetEnter t]
ws <- webSocket wsurl $ def & webSocketConfig_send .~ newMessage
receivedMessages <- foldDyn (\m ms -> ms ++ [m]) [] $ _webSocket_recv ws
el "p" $ text "Responses from :"
_ <- el "ul" $ simpleList receivedMessages $ \m -> el "li" $ dynText =<< mapDyn (T.unpack . decodeUtf8) m
return ()
I feel like there should be a way to do this with tickLossy to send pings with timeout, like some dynamic which returns websockets and then reconnects if a ping goes a certain amount of time without a response? But I'm having trouble envisioning what the code to reconnect would look like.
Edit: It was an issue with reflex-dom sending an event while a websocket was still in the pending state. I made a pull request, although I feel there is a better solution somewhere.
Edit: It was an issue with reflex-dom sending an event while a websocket was still in the pending state. I made a pull request, although I feel there is a better solution somewhere.
Just FYI, since the question was posted there have been some quite relevant extensions to the WebSocket API merged into reflex-dom:
Event
s, see _webSocketConfig_close
_webSocketConfig_reconnect
Event
exposed for when the connection is closed, see _webSocket_close
Event
exposed for when an error occurs, see _webSocket_error
I believe the close event is exactly what you were looking for. It was just not available at the time.