on develop help sign in
websockets: queue messages while not open

also fixes messages sent while ws connecting

commitc18a0a57f825af72d55b3c1b1398ce02b8fbf952 authorAttila Sztupak <attila.sztupak@gmail.com> dateMon 1 Feb 2016, 17:26 (11 years ago) parent8911714
2 files changed+32−11
reflex-dom.cabal+3−1 src/Reflex/Dom/WebSocket.hs+29−10
reflex-dom.cabal+3−1
@@ -22,6 +22,7 @@ library
2222 hs-source-dirs: src
2323 build-depends:
2424 base >= 4.7 && < 4.9,
25+ stm == 2.4.*,
2526 reflex == 0.4.*,
2627 dependent-sum == 0.3.*,
2728 dependent-map == 0.2.*,
@@ -42,7 +43,8 @@ library
4243 exception-transformers == 0.4.*,
4344 directory == 1.2.*,
4445 dependent-sum-template >= 0.0.0.4 && < 0.1,
45− bifunctors >= 4.2 && < 6
46+ bifunctors >= 4.2 && < 6,
47+ ghcjs-prim == 0.1.*
4648
4749 if impl(ghcjs)
4850 hs-source-dirs: src-ghcjs
src/Reflex/Dom/WebSocket.hs+29−10
@@ -10,11 +10,15 @@ import Reflex.Dom.Class
1010import Reflex.Dom.WebSocket.Foreign
1111
1212import Control.Concurrent
13+import Control.Concurrent.STM
14+import Control.Exception (catch, SomeException)
1315import Control.Lens
1416import Control.Monad hiding (forM, forM_, mapM, mapM_, sequence)
1517import Control.Monad.IO.Class
1618import Control.Monad.Ref
1719import Control.Monad.State
20+import Control.Arrow (second)
21+import Data.Maybe (isJust)
1822import Data.ByteString (ByteString)
1923import Data.Default
2024import Data.Dependent.Map (DSum (..))
@@ -41,6 +45,8 @@ webSocket url config = do
4145 currentSocketRef <- liftIO $ newIORef Nothing
4246 --TODO: Disconnect if value no longer needed
4347 (eOpen, eOpenTriggerRef) <- newEventWithTriggerRef
48+ payloadQueue <- liftIO newTQueueIO
49+ isOpen <- liftIO newEmptyTMVarIO
4450 let onMessage :: ByteString -> IO ()
4551 onMessage m = postGui $ do
4652 mt <- readRef eRecvTriggerRef
@@ -48,21 +54,34 @@ webSocket url config = do
4854 onOpen = postGui $ do
4955 mt <- readRef eOpenTriggerRef
5056 forM_ mt $ \t -> runWithActions [t :=> Identity ()]
57+ liftIO $ void $ atomically $ tryPutTMVar isOpen ()
58+ --TODO: Is the fork necessary, or do event handlers run in their own threads automatically?
59+ onClose = void $ forkIO $ do
60+ liftIO $ atomically $ tryTakeTMVar isOpen
61+ liftIO $ writeIORef currentSocketRef Nothing
62+ liftIO $ threadDelay 1000000
63+ start
5164 start = do
52− ws <- liftIO $ newWebSocket wv url onMessage onOpen $ do
53− void $ forkIO $ do --TODO: Is the fork necessary, or do event handlers run in their own threads automatically?
54− liftIO $ writeIORef currentSocketRef Nothing
55− liftIO $ threadDelay 1000000
56− start
65+ ws <- liftIO $ newWebSocket wv url onMessage onOpen onClose
5766 liftIO $ writeIORef currentSocketRef $ Just ws
5867 return ()
5968 schedulePostBuild $ liftIO start
60− performEvent_ $ ffor (_webSocketConfig_send config) $ \payloads -> forM_ payloads $ \payload -> do
69+ performEvent_ $ ffor (_webSocketConfig_send config) $ \payloads -> forM_ payloads $ \payload ->
70+ liftIO $ atomically $ writeTQueue payloadQueue payload
71+
72+ liftIO $ forkIO $ forever $ do
73+ payload <- atomically $ do
74+ pl <- readTQueue payloadQueue
75+ open <- tryReadTMVar isOpen
76+ if isJust open then return pl else retry
77+
6178 mws <- liftIO $ readIORef currentSocketRef
62− case mws of
63− Nothing -> return () -- Discard --TODO: should we do something better here? probably buffer it, since we handle reconnection logic; how do we verify that the server has received things?
64− Just ws -> do
65− liftIO $ webSocketSend ws payload
79+ succ <- case mws of
80+ Nothing -> return False
81+ Just ws -> liftIO ((webSocketSend ws payload >> return True)
82+ `catch`
83+ (\(_ :: SomeException) -> return False))
84+ unless succ $ atomically $ unGetTQueue payloadQueue payload
6685 return $ WebSocket eRecv eOpen
6786
6887makeLensesWith (lensRules & simpleLenses .~ True) ''WebSocketConfig