Skip to content

Commit 4e5af36

Browse files
committed
fix ws memory issues
1 parent 8d5f633 commit 4e5af36

File tree

2 files changed

+45
-27
lines changed

2 files changed

+45
-27
lines changed

service/src/Foundation.hs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,18 @@ data App = App
4343
type ServerMessage = LBS.ByteString
4444

4545
data LobbyState = LobbyState
46-
{ lobbyClients :: Map UserId (TBQueue ServerMessage),
47-
lobbyRaceState :: Maybe RaceState
46+
{ lobbyClients :: !(Map UserId (TBQueue ServerMessage)),
47+
lobbyRaceState :: !(Maybe RaceState)
4848
}
4949

5050
data RaceState = RaceState
51-
{ raceEra :: Text,
52-
raceWordCount :: Int,
53-
raceStartTime :: Maybe UTCTime,
54-
raceProgress :: Map UserId Int, -- character index
55-
raceWPM :: Map UserId Double, -- current WPM
56-
raceCompleted :: Map UserId (Double, Double), -- final (wpm, accuracy)
57-
raceTextLength :: Int
51+
{ raceEra :: !Text,
52+
raceWordCount :: !Int,
53+
raceStartTime :: !(Maybe UTCTime),
54+
raceProgress :: !(Map UserId Int), -- character index
55+
raceWPM :: !(Map UserId Double), -- current WPM
56+
raceCompleted :: !(Map UserId (Double, Double)), -- final (wpm, accuracy)
57+
raceTextLength :: !Int
5858
}
5959

6060
-- This function also generates the following type synonyms:

service/src/Handler/MultiplayerWs.hs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE BangPatterns #-}
12
{-# LANGUAGE NamedFieldPuns #-}
23
{-# LANGUAGE OverloadedStrings #-}
34
{-# LANGUAGE RecordWildCards #-}
@@ -81,6 +82,10 @@ getMultiplayerWsR lobbyId = do
8182
atomically $
8283
modifyTVar' lobbiesTVar (Map.alter (removeClient userId) lobbyId)
8384
cleanup = do
85+
liftIO . atomically $
86+
writeTBQueue chan $
87+
encode $
88+
object ["type" .= ("close" :: Text)]
8489
liftIO removeClientIO
8590
liftIO $ broadcastState pool lobbiesTVar lobbyId
8691

@@ -103,21 +108,34 @@ sendLoop chan = forever $ do
103108
msg <- liftIO $ atomically $ readTBQueue chan
104109
sendTextData msg
105110

106-
receiveLoop :: ConnectionPool -> TVar (Map Text LobbyState) -> Text -> UserId -> WebSocketsT Handler ()
107-
receiveLoop pool lobbiesTVar lobbyUId userId = forever $ do
108-
msgE <- receiveDataMessageE
109-
case msgE of
110-
Left se ->
111-
liftIO $ throwIO se
112-
Right (WS.Text bs _mText) -> do
113-
let txt = decodeUtf8 (LBS.toStrict bs)
114-
case parseMessage txt of
115-
Just cm ->
116-
liftIO $
117-
handleClientMessage pool lobbiesTVar lobbyUId userId cm
118-
Nothing -> pure () -- Ignore invalid messages
119-
Right (WS.Binary _bs) -> do
120-
pure ()
111+
receiveLoop ::
112+
ConnectionPool ->
113+
TVar (Map Text LobbyState) ->
114+
Text ->
115+
UserId ->
116+
WebSocketsT Handler ()
117+
-- Normal-closure frames are swallowed so they don’t reach Warp’s logger.
118+
receiveLoop pool lobbiesTVar lobbyUId userId = loop
119+
where
120+
loop = do
121+
msgE <- receiveDataMessageE
122+
case msgE of
123+
Left se ->
124+
case (fromException se :: Maybe WS.ConnectionException) of
125+
Just (WS.CloseRequest 1000 _) -> pure ()
126+
Just (WS.CloseRequest 1001 _) -> pure ()
127+
Just WS.ConnectionClosed -> pure ()
128+
_ -> liftIO $ throwIO se
129+
Right (WS.Text bs _mText) -> do
130+
let txt = decodeUtf8 (LBS.toStrict bs)
131+
case parseMessage txt of
132+
Just cm ->
133+
liftIO $
134+
handleClientMessage pool lobbiesTVar lobbyUId userId cm
135+
Nothing -> pure () -- Ignore invalid messages
136+
loop
137+
Right (WS.Binary _bs) ->
138+
loop
121139

122140
-- Parse incoming WebSocket messages
123141
parseMessage :: Text -> Maybe ClientMessage
@@ -168,13 +186,13 @@ startRace era wordCount startTime ls =
168186
}
169187

170188
updateProgress :: UserId -> Int -> Double -> LobbyState -> LobbyState
171-
updateProgress userId charIndex wpm ls@LobbyState {lobbyRaceState = Just rs} =
189+
updateProgress uid !charIdx !wpm ls@LobbyState {lobbyRaceState = Just rs} =
172190
ls
173191
{ lobbyRaceState =
174192
Just
175193
rs
176-
{ raceProgress = Map.insert userId charIndex (raceProgress rs),
177-
raceWPM = Map.insert userId wpm (raceWPM rs)
194+
{ raceProgress = Map.insert uid charIdx (raceProgress rs),
195+
raceWPM = Map.insert uid wpm (raceWPM rs)
178196
}
179197
}
180198
updateProgress _ _ _ ls = ls

0 commit comments

Comments
 (0)